Files
nlcc-itinerary/README.md
Joshua Ryder 3474ca7013 refactor: Use external Docker named volume for data persistence
Changes:
- Replace bind mount (./data) with external named volume (nlcc-data)
- Volume must be created before first run: docker volume create nlcc-data
- Improves portability and follows Docker best practices
- Better separation between code and data

Benefits:
- Data persists across container rebuilds and updates
- Easier backup and restore operations
- Platform-agnostic (works same on Linux/Windows/macOS)
- Managed by Docker's volume system
- No permission issues with bind mounts

README Updates:
- Added volume creation step to installation instructions
- Documented volume management commands (create, inspect, backup, restore)
- Added backup/restore examples using alpine container
- Clarified data persistence behavior

Note: Existing deployments using ./data bind mount will need to:
1. Backup existing data: cp -r ./data ./data-backup
2. Create volume: docker volume create nlcc-data
3. Restart container: docker-compose up -d
4. Copy data to volume if needed

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-05 17:46:07 -05:00

13 KiB

New Life Christian Church - Sermon Itinerary

A web application for managing and displaying weekly sermons for New Life Christian Church.

Features

  • 📝 Sermon Management: Create and manage sermon content with a user-friendly form
  • 🔐 Enterprise Security: OWASP-compliant authentication with CSRF protection, session management, and account lockout
  • 👥 User Management: Full admin panel for managing users, roles, and account security
  • 🔒 Password Security: Bcrypt hashing, strong password requirements, and secure password reset with 8-character alphanumeric codes
  • 🛡️ Account Protection: Dual-layer brute force protection (IP-based + per-account lockout)
  • 📱 QR Codes: Generate QR codes for easy sermon sharing
  • 📅 Date-based URLs: Sermons accessible via sermon-MMDDYYYY format
  • 🎨 Modern UI: Clean, responsive design using Tailwind CSS and Inter font
  • 📊 Three Sections: Bible References, Personal Appliance, and Pastor's Challenge
  • 🗂️ Smart Organization: Recent sermons (last 3 months) displayed by default, older sermons in dropdown
  • 📧 Email Notifications: Password reset codes and sermon notes via SMTP
  • 🐳 Docker Ready: Fully containerized for easy deployment with auto-generated secrets

Technology Stack

  • Frontend: Nuxt 3 (Vue.js)
  • Styling: Tailwind CSS with Inter font from Google Fonts
  • Database: SQLite
  • QR Codes: qrcode library
  • Deployment: Docker & Docker Compose

Configuration

This application uses environment variables configured directly in docker-compose.yml. Edit the file to customize your deployment settings.

Environment Variables

Variable Description Default Required
SITE_URL Public URL where the app is hosted (used for QR codes) https://nlcc.rydertech.us Yes
AUTH_SECRET Secret key for authentication sessions Auto-generated No
ADMIN_USERNAME Initial admin login username admin No
ADMIN_PASSWORD Initial admin login password Auto-generated No
EMAIL_HOST SMTP server hostname smtp.example.com Yes
EMAIL_PORT SMTP server port 587 Yes
EMAIL_USER SMTP authentication username noreply@example.com Yes
EMAIL_PASSWORD SMTP authentication password Required Yes
EMAIL_FROM Email sender address and name New Life Christian Church <noreply@example.com> Yes

Security Note: AUTH_SECRET and ADMIN_PASSWORD are now automatically generated on first launch using cryptographically secure random generation. They are stored in the database and logged once to container logs.

Customizing Configuration

Edit docker-compose.yml and update the required values:

services:
  nlcc-itinerary:
    environment:
      - SITE_URL=https://your-church-domain.com
      # Optional: customize admin username (default: "admin")
      # - ADMIN_USERNAME=your-admin-username
      # Optional: set custom admin password (otherwise auto-generated)
      # - ADMIN_PASSWORD=your-secure-password
      # Email configuration (required for password resets)
      - EMAIL_HOST=smtp.gmail.com
      - EMAIL_PORT=587
      - EMAIL_USER=your-email@gmail.com
      - EMAIL_PASSWORD=your-app-password
      - EMAIL_FROM=Your Church Name <your-email@gmail.com>

Note: AUTH_SECRET is no longer needed in configuration - it's automatically generated and stored in the database on first launch.

Getting Started

Prerequisites

  • Docker and Docker Compose installed on your system

Installation & Deployment

  1. Clone the repository:
git clone <repository-url>
cd nlcc-itinerary
  1. Edit docker-compose.yml and configure your settings:

    • Update SITE_URL to your public domain
    • Configure email settings (required for password resets)
    • Optionally set ADMIN_USERNAME and ADMIN_PASSWORD (otherwise auto-generated)
  2. Create the external Docker volume for data persistence:

docker volume create nlcc-data
  1. Build and run with Docker Compose:
docker-compose up -d --build

The application will be available at http://localhost:3002 (or your configured port)

Important: The SITE_URL must be set correctly for QR codes to work. This should be the public URL where your application is accessible (e.g., https://church.example.com).

Initial Admin Account

The initial admin account is created automatically on first run with secure auto-generated credentials:

Default behavior:

  • Username: admin (can be customized with ADMIN_USERNAME env var)
  • Password: Auto-generated (cryptographically secure 16-character password)

Retrieving Auto-Generated Credentials:

# View the auto-generated admin password from container logs
docker logs nlcc-itinerary 2>&1 | grep "ADMIN CREDENTIALS"

The output will show:

╔════════════════════════════════════════════════════════╗
║          🔐 ADMIN CREDENTIALS (SAVE THESE!)           ║
╠════════════════════════════════════════════════════════╣
║ Username: admin                                        ║
║ Password: <randomly-generated-password>                ║
╚════════════════════════════════════════════════════════╝

⚠️ Important:

  • Credentials are logged only once on first startup
  • Save the credentials immediately - they won't be shown again
  • Alternatively, set ADMIN_PASSWORD in docker-compose.yml to use a custom password
  • Change admin password after first login via the profile page
  • Additional users and admins can be created through the user management interface

Project Structure

nlcc-itinerary/
├── assets/css/          # Global styles
├── components/          # Vue components
│   ├── SermonCard.vue
│   ├── QRCodeButton.vue
│   └── QRCodeModal.vue
├── middleware/          # Route middleware
│   └── auth.ts
├── pages/              # Application pages
│   ├── index.vue       # Main sermon listing
│   ├── login.vue       # Login page
│   ├── register.vue    # User registration
│   ├── admin.vue       # Sermon creation form
│   ├── users.vue       # User management (admin only)
│   ├── profile.vue     # User profile settings
│   └── [slug].vue      # Individual sermon page
├── plugins/            # Nuxt plugins
│   └── csrf.client.ts  # CSRF auto-injection
├── server/
│   ├── api/            # API endpoints
│   │   ├── auth/       # Authentication endpoints
│   │   ├── sermons/    # Sermon CRUD endpoints
│   │   ├── users/      # User management endpoints
│   │   └── profile/    # Profile management
│   ├── middleware/     # Server middleware
│   │   └── csrf.ts     # CSRF validation
│   └── utils/          # Server utilities
│       ├── database.ts # SQLite database functions
│       ├── auth.ts     # Authentication helpers
│       ├── csrf.ts     # CSRF protection utilities
│       └── email.ts    # Email sending functions
├── logos/              # Church logos
├── Dockerfile          # Docker configuration
├── docker-compose.yml  # Docker Compose configuration
└── nuxt.config.ts      # Nuxt configuration

Usage

Creating a Sermon

  1. Navigate to /login and sign in with admin credentials
  2. You'll be redirected to /admin
  3. Fill in the sermon details:
    • Date: Select the sermon date (URL will be auto-generated as sermon-MMDDYYYY)
    • Title: Enter the sermon title
    • Bible References: Add one or more Bible verses (use +/- buttons)
    • Personal Appliance: Enter personal application content
    • Pastor's Challenge: Enter the pastor's challenge content
  4. Click "Create Sermon"

Viewing Sermons

  • Main Page (/): Shows recent sermons (last 3 months) with option to view older ones
  • Individual Sermon (/sermon-MMDDYYYY): Full sermon details with QR code
  • QR Code: Click the QR code button on any sermon card or page to generate a scannable code

Database

The application uses SQLite with the following schema:

Sermons Table

  • id: Primary key
  • slug: Unique sermon identifier (e.g., sermon-09282025)
  • title: Sermon title
  • date: Sermon date
  • bible_references: Newline-separated Bible verses
  • personal_appliance: Personal application content
  • pastors_challenge: Pastor's challenge content
  • created_at: Timestamp

Users Table

  • id: Primary key
  • username: User's username (unique)
  • password: User's password (bcrypt hashed)
  • first_name: User's first name
  • last_name: User's last name
  • email: User's email address
  • is_admin: Admin flag (0 or 1)
  • failed_login_attempts: Failed login counter
  • locked_until: Account lock expiration timestamp
  • created_at: Account creation timestamp

Sessions Table

  • id: Primary key
  • token: Session token (unique)
  • username: Associated username
  • expires_at: Session expiration timestamp
  • csrf_token: CSRF token for request validation
  • created_at: Session creation timestamp

Settings Table

  • key: Setting key (primary)
  • value: Setting value
  • created_at: Creation timestamp
  • updated_at: Last update timestamp

Security Features

This application implements enterprise-grade security following OWASP best practices:

Implemented Security Features

  1. Auto-Generated Secrets

    • AUTH_SECRET automatically generated using cryptographic randomness
    • Admin password auto-generated with 16 characters (uppercase, lowercase, numbers, symbols)
    • All secrets stored securely in database
  2. Password Security

    • Bcrypt hashing with 10 salt rounds
    • Strong password requirements (8+ chars, uppercase, lowercase, number/symbol)
    • Secure password reset with 8-character alphanumeric codes (1.8 trillion combinations)
    • Session invalidation on password changes
  3. CSRF Protection

    • Double-submit cookie pattern implementation
    • Automatic token injection on all API requests
    • Three-way validation (cookie, header, session database)
    • Zero configuration needed in components
  4. Session Management

    • Secure session tokens with HTTP-only cookies
    • Automatic session expiration (24 hours)
    • Session invalidation on security events (password changes, admin resets)
    • Protection against session fixation attacks
  5. Account Lockout (Dual-Layer Brute Force Protection)

    • IP-based rate limiting (existing)
    • Per-account lockout: 10 failed attempts = 30 minute lock
    • Automatic unlock after expiration
    • Admin manual unlock capability via UI
  6. User Management

    • Role-based access control (admin/user)
    • Admin dashboard for user management
    • Account lock status visibility
    • Password reset functionality

🔒 Production Recommendations

  1. Strong passwords - Enforced by application
  2. Password hashing - Bcrypt with salt rounds
  3. CSRF protection - Implemented
  4. Session security - HTTP-only cookies with expiration
  5. Account lockout - Dual-layer protection
  6. Secrets management - Auto-generated and stored securely
  7. Enable HTTPS - Configure reverse proxy (nginx/Caddy)
  8. Regular backups - Backup /app/data directory
  9. Email security - Use app-specific passwords for SMTP
  10. Monitor logs - Review failed login attempts

🛡️ Security Compliance

  • OWASP Top 10 2021: Addressed broken authentication, injection, security misconfiguration
  • Password Storage: NIST-compliant bcrypt hashing
  • CSRF Protection: Industry-standard double-submit pattern
  • Session Security: Secure cookie attributes and expiration
  • Brute Force Protection: Account lockout + rate limiting

Docker Commands

# Build and start
docker-compose up -d

# View logs
docker-compose logs -f

# Stop containers
docker-compose down

# Rebuild after changes
docker-compose up -d --build

# Access container shell
docker exec -it nlcc-itinerary sh

Data Persistence

The SQLite database is stored in a Docker named volume (nlcc-data) which is mounted to /app/data in the container. This ensures:

  • Data persists across container restarts and rebuilds
  • Better portability across different environments
  • Easier backup and restore operations
  • Managed by Docker volume system

Volume Management Commands:

# Create the volume (required before first run)
docker volume create nlcc-data

# Inspect volume location and details
docker volume inspect nlcc-data

# Backup the database
docker run --rm -v nlcc-data:/data -v $(pwd):/backup alpine tar czf /backup/nlcc-backup.tar.gz -C /data .

# Restore from backup
docker run --rm -v nlcc-data:/data -v $(pwd):/backup alpine tar xzf /backup/nlcc-backup.tar.gz -C /data

# Remove volume (WARNING: deletes all data!)
docker volume rm nlcc-data

License

This project is created for New Life Christian Church.

Support

For issues or questions, please contact the development team.