Deploying FoodCoopShop
Introduction
FoodCoopShop is a user-friendly open-source software platform designed specifically for food cooperatives and local shops. Built with CakePHP, this comprehensive solution empowers communities to manage online ordering, inventory, member management, and producer relationships all in one place. Whether you’re running a food co-op or a local farm shop, FoodCoopShop provides the tools you need to connect producers directly with consumers.
FoodCoopShop is known for:
- Cooperative-First Design: Purpose-built for food cooperatives with features that match real-world workflows
- Multi-Producer Support: Manage products from multiple local producers and farmers in one platform
- Flexible Delivery Rhythms: Configure various delivery schedules (weekly, bi-weekly, monthly, or custom)
- Member Management: Complete member registration, order tracking, and account management
- Cashless Payment System: Built-in payment tracking based on bank account transfers
- Order Adaptations: Easy order cancellation and price/weight adjustments
- Self-Service Mode: Optional self-service functionality with barcode scanning support
- Decentralized Network: Synchronize products across multiple FoodCoopShop installations
- Multi-Language: Available in German and English with growing language support
- Admin Dashboard: Comprehensive admin area for both manufacturers and cooperative administrators
Common use cases include food cooperatives, farm-to-table initiatives, community-supported agriculture (CSA) programs, local food shops, farmers’ markets, and regional food networks.
This comprehensive guide walks you through deploying FoodCoopShop on Klutch.sh using Docker, including MySQL database configuration, persistent storage setup, environment variables, and production-ready best practices.
Why Deploy FoodCoopShop on Klutch.sh?
- Simplified Infrastructure: No need to manage servers, databases, or complex configurations manually
- Persistent Storage: Reliable volume storage for product images, documents, and uploads
- MySQL Integration: Easy database setup with persistent data storage
- Automatic HTTPS: Secure connections out of the box for safe transactions
- Environment Variables: Secure configuration management without hardcoding credentials
- Easy Scaling: Scale resources as your cooperative grows
- Cost-Effective: Pay only for what you use with transparent pricing
Prerequisites
Before you begin, ensure you have the following:
- A Klutch.sh account
- A GitHub account with a repository for your FoodCoopShop project
- Docker installed locally for testing (optional but recommended)
- Basic understanding of Docker, PHP applications, and MySQL databases
- A MySQL database (either external or deployed on Klutch.sh - see our MySQL deployment guide)
Installation and Setup
Step 1: Create Your Project Directory
First, create a new directory for your FoodCoopShop deployment project:
mkdir foodcoopshop-klutchcd foodcoopshop-klutchgit initStep 2: Create the Dockerfile
Create a Dockerfile in your project root directory. This will define your FoodCoopShop container configuration using the official Docker image:
FROM foodcoopshop/foodcoopshop:latest
# FoodCoopShop runs on Apache with PHP-FPM# The official image already includes Apache and all required PHP extensionsEXPOSE 80
# The base image includes:# - Apache 2.4 with mod_rewrite enabled# - PHP 8.4+ with required extensions (intl, imagick, gd, bzip2, pdo_mysql)# - CakePHP 5.x framework# - All FoodCoopShop application code
# Persistent volumes should be mounted at:# /var/www/html/files_private - for uploaded files and documents# /var/www/html/webroot/files - for public assets and product images# /var/www/html/tmp - for cache and temporary files
# Environment variables for database connection# These should be configured in the Klutch.sh dashboard# DATABASE_URL format: mysql://username:password@host:3306/database_nameKey points about the Dockerfile:
- Uses the official
foodcoopshop/foodcoopshop:latestimage - Exposes port 80 for HTTP traffic
- Requires MySQL database connection via environment variables
- Needs persistent volumes for file storage and caching
Step 3: Create a Configuration Template
Create a custom_config.example.php file to document the required configuration. This file serves as a template and should NOT contain actual credentials:
<?php/** * FoodCoopShop Custom Configuration Template * * Copy this file to custom_config.php and update with your actual values. * DO NOT commit custom_config.php with real credentials to version control. */
return [ // Database Configuration 'Datasources' => [ 'default' => [ 'host' => 'your-mysql-host.klutch.sh', 'port' => 8000, // TCP port for Klutch.sh MySQL service 'username' => 'your_database_user', 'password' => 'your_database_password', 'database' => 'foodcoopshop_production', ], ],
// Application Configuration 'App' => [ 'fullBaseUrl' => 'https://example-app.klutch.sh', 'cakeServerName' => 'Klutch Production', 'EmailTransport' => [ 'default' => [ 'className' => 'Smtp', 'host' => 'your-smtp-host', 'port' => 587, 'username' => 'your-smtp-username', 'password' => 'your-smtp-password', 'tls' => true, ], ], ],
// Security 'Security' => [ 'salt' => 'your-unique-security-salt-here', ],
// Session Configuration 'Session' => [ 'timeout' => 2592000, // 30 days in seconds 'cookieTimeout' => 2592000, ],];Step 4: Create a README for Documentation
Create a README.md file to document your deployment:
# FoodCoopShop Deployment
This repository contains the Docker configuration for deploying FoodCoopShop on Klutch.sh.
## Environment Variables Required
Configure these in the Klutch.sh dashboard:
- `DATABASE_URL`: MySQL connection string (format: mysql://user:pass@host:port/db_name)- `APP_FULL_BASE_URL`: Your application URL (e.g., https://example-app.klutch.sh)- `SECURITY_SALT`: Random string for encryption (generate with: openssl rand -base64 32)- `EMAIL_HOST`: SMTP server hostname- `EMAIL_PORT`: SMTP server port (usually 587 for TLS)- `EMAIL_USERNAME`: SMTP authentication username- `EMAIL_PASSWORD`: SMTP authentication password
## Persistent Volumes
Mount these paths in Klutch.sh:
1. `/var/www/html/files_private` - Private uploaded files (minimum 5GB recommended)2. `/var/www/html/webroot/files` - Public product images (minimum 10GB recommended)3. `/var/www/html/tmp` - Cache and temporary files (minimum 1GB)
## Database Setup
Before deploying, ensure you have a MySQL 8.0+ database ready.See the Klutch.sh MySQL deployment guide for setup instructions.
## First-Time Setup
After deployment, access your FoodCoopShop instance and follow the setup wizard to:1. Create the admin account2. Configure cooperative settings3. Set up payment methods4. Add producers and product categoriesStep 5: Create a .gitignore File
Create a .gitignore file to exclude sensitive files from version control:
# Custom configuration with credentialscustom_config.php
# Local development files*.local.env
# PHP dependencies (if using composer locally)vendor/composer.lock
# Temporary and cache filestmp/logs/
# IDE files.vscode/.idea/*.swp*.swo
# OS files.DS_StoreThumbs.dbStep 6: Commit to GitHub
Push your configuration to GitHub:
git add Dockerfile custom_config.example.php README.md .gitignoregit commit -m "Add FoodCoopShop deployment configuration"git remote add origin https://github.com/yourusername/foodcoopshop-klutch.gitgit push -u origin mainDeploying to Klutch.sh
Now that your FoodCoopShop project is ready and pushed to GitHub, follow these steps to deploy it on Klutch.sh.
Deployment Steps
-
Prepare Your MySQL Database
FoodCoopShop requires a MySQL 8.0+ database. You have two options:
Option A: Deploy MySQL on Klutch.sh
- Follow our MySQL deployment guide
- Note the connection details (host, port 8000, username, password, database name)
Option B: Use an External MySQL Service
- Use a managed MySQL service like Amazon RDS, DigitalOcean Managed Databases, or PlanetScale
- Ensure the service allows connections from Klutch.sh
- Note the connection details
-
Log in to Klutch.sh
Navigate to klutch.sh/app and sign in to your account.
-
Create a New Project
Go to Create Project and give your project a meaningful name (e.g., “FoodCoopShop Production”).
-
Create a New App
Navigate to Create App within your project.
-
Connect Your Repository
- Select GitHub as your Git source
- Choose the repository containing your Dockerfile
- Select the branch you want to deploy (typically
mainormaster)
-
Configure Traffic Settings
- Traffic Type: Select HTTP (FoodCoopShop is a web application)
- Internal Port: Set to
80(Apache listens on port 80 in the container)
-
Set Environment Variables
Add the following environment variables in the Klutch.sh dashboard. Mark sensitive values as secrets:
Database Configuration:
DATABASE_HOST: Your MySQL host (e.g.,mysql-app.klutch.shor external host)DATABASE_PORT:8000(for Klutch.sh MySQL) or your external database portDATABASE_NAME:foodcoopshop_productionDATABASE_USER: Your database usernameDATABASE_PASSWORD: Your database password (mark as secret)DATABASE_URL: Full connection string:mysql://user:password@host:port/database_name
Application Configuration:
APP_FULL_BASE_URL: Your application URL (e.g.,https://example-app.klutch.sh)SECURITY_SALT: Generate withopenssl rand -base64 32(mark as secret)APP_ENV:productionDEBUG:false
Email Configuration (SMTP):
EMAIL_HOST: Your SMTP server hostnameEMAIL_PORT: SMTP port (typically587for TLS or465for SSL)EMAIL_USERNAME: SMTP usernameEMAIL_PASSWORD: SMTP password (mark as secret)EMAIL_FROM: Sender email address (e.g.,noreply@yourfoodcoop.org)EMAIL_FROM_NAME: Sender name (e.g.,Your Food Coop)
Optional Configuration:
SESSION_TIMEOUT: Session timeout in seconds (default:2592000= 30 days)LOCALE: Default language (enfor English,defor German)
-
Attach Persistent Volumes
FoodCoopShop requires persistent storage for uploaded files, product images, and cache. Create three volumes:
Volume 1: Private Files
- Mount Path:
/var/www/html/files_private - Size:
5GBminimum (increase based on expected document uploads) - Purpose: Stores private uploaded documents, invoices, and member files
Volume 2: Public Files (Product Images)
- Mount Path:
/var/www/html/webroot/files - Size:
10GBminimum (increase based on product catalog size) - Purpose: Stores product images, category images, and public assets
Volume 3: Cache and Temporary Files
- Mount Path:
/var/www/html/tmp - Size:
1GBminimum - Purpose: Stores CakePHP cache, sessions, and temporary files
- Mount Path:
-
Configure Resources
- CPU: Start with 1 CPU, scale up if needed
- Memory: Minimum 1GB RAM recommended, 2GB+ for production workloads
- Instances: Start with 1, scale horizontally as your cooperative grows
-
Deploy Your Application
Click “Create” to start the deployment. Klutch.sh will:
- Detect your Dockerfile automatically
- Build the Docker image with FoodCoopShop
- Configure the environment variables
- Mount the persistent volumes
- Start the Apache/PHP container
- Assign a public URL
-
Initialize the Database
After deployment completes:
- Access your FoodCoopShop URL (e.g.,
https://example-app.klutch.sh) - The first-time setup wizard will guide you through:
- Database schema creation and migration
- Initial admin account creation
- Basic cooperative configuration
- Email settings verification
- Access your FoodCoopShop URL (e.g.,
-
Complete Initial Configuration
In the admin dashboard, configure:
- Cooperative Information: Name, address, contact details, logo
- Payment Methods: Bank account details for cashless payment system
- Delivery Rhythms: Weekly, bi-weekly, or custom delivery schedules
- Product Categories: Organize your product catalog
- Tax Rates: Configure applicable tax rates for your region
- Member Groups: Set up member types and permissions
- Email Templates: Customize notification emails
Post-Deployment Configuration
Adding Producers
- Navigate to Admin → Producers in the dashboard
- Click “Add New Producer”
- Fill in producer details:
- Name and contact information
- Bank account details (for payments)
- Delivery settings
- Commission rates
- Assign product categories the producer can use
- Configure notification preferences
Creating Product Catalog
- Go to Products → Add New Product
- Configure product details:
- Name and description
- Producer/manufacturer
- Category and subcategory
- Price and tax rate
- Unit (kg, g, piece, liter, etc.)
- Stock quantity (if using inventory management)
- Product image upload
- Set delivery rhythm (weekly, bi-weekly, specific days)
- Configure purchase limits if needed
- Set product status (active/inactive)
Member Registration
FoodCoopShop supports two registration modes:
Self-Registration:
- Enable public registration on the website
- New members fill out registration form
- Admin approval required before account activation
- Members receive welcome email with login credentials
Admin-Created Accounts:
- Admin creates member accounts directly
- Useful for existing cooperatives migrating to the platform
- Members receive invitation email
Payment System Setup
FoodCoopShop uses a cashless payment system based on bank transfers:
- Configure Bank Details: Add your cooperative’s bank account information
- Credit System: Members pre-pay credit to their account
- Order Deductions: Orders automatically deduct from member credit
- Payment Tracking: Admin can match bank transfers with member payments
- Balance Reports: Members see their current credit balance
Email Notifications
FoodCoopShop sends automated emails for:
- Order confirmations
- Order status changes
- Payment reminders
- Product availability notifications
- Weekly order reminders
- Producer order summaries
Configure email templates in Admin → Email Templates.
Sample API Integration
While FoodCoopShop primarily uses its web interface, you can interact with the CakePHP backend programmatically for custom integrations.
PHP Example: Custom Product Import Script
<?php/** * Example: Bulk Product Import Script * This demonstrates how to interact with FoodCoopShop's database */
// Database connection using PDO$host = getenv('DATABASE_HOST');$port = getenv('DATABASE_PORT');$dbname = getenv('DATABASE_NAME');$username = getenv('DATABASE_USER');$password = getenv('DATABASE_PASSWORD');
try { $pdo = new PDO( "mysql:host=$host;port=$port;dbname=$dbname;charset=utf8mb4", $username, $password, [ PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, ] );
// Example: Insert a new product $stmt = $pdo->prepare(" INSERT INTO fcs_product ( name, description, manufacturer_id, category_id, price, tax_rate, active, created, modified ) VALUES ( :name, :description, :manufacturer_id, :category_id, :price, :tax_rate, 1, NOW(), NOW() ) ");
$stmt->execute([ 'name' => 'Organic Apples', 'description' => 'Fresh organic apples from local farm', 'manufacturer_id' => 1, 'category_id' => 2, 'price' => 3.50, 'tax_rate' => 10.0, ]);
echo "Product inserted successfully with ID: " . $pdo->lastInsertId();
} catch (PDOException $e) { echo "Database Error: " . $e->getMessage();}Python Example: Order Export Script
#!/usr/bin/env python3"""Example: Export orders to CSV for reporting"""
import osimport csvimport mysql.connectorfrom datetime import datetime
def export_orders_to_csv(): # Database connection connection = mysql.connector.connect( host=os.getenv('DATABASE_HOST'), port=int(os.getenv('DATABASE_PORT', 3306)), user=os.getenv('DATABASE_USER'), password=os.getenv('DATABASE_PASSWORD'), database=os.getenv('DATABASE_NAME') )
cursor = connection.cursor(dictionary=True)
# Query orders from the last week query = """ SELECT o.id AS order_id, o.created AS order_date, m.firstname, m.lastname, m.email, p.name AS product_name, od.product_amount, od.total_price_tax_incl FROM fcs_order o JOIN fcs_member m ON o.member_id = m.id JOIN fcs_order_detail od ON o.id = od.order_id JOIN fcs_product p ON od.product_id = p.id WHERE o.created >= DATE_SUB(NOW(), INTERVAL 7 DAY) ORDER BY o.created DESC """
cursor.execute(query) orders = cursor.fetchall()
# Export to CSV filename = f'orders_export_{datetime.now().strftime("%Y%m%d")}.csv'
with open(filename, 'w', newline='') as csvfile: if orders: fieldnames = orders[0].keys() writer = csv.DictWriter(csvfile, fieldnames=fieldnames) writer.writeheader() writer.writerows(orders)
print(f"Exported {len(orders)} orders to {filename}")
cursor.close() connection.close()
if __name__ == '__main__': export_orders_to_csv()JavaScript Example: Member Balance Check
// Example: Check member account balance via API callconst axios = require('axios');
const FOODCOOPSHOP_URL = 'https://example-app.klutch.sh';
async function checkMemberBalance(memberId) { try { // FoodCoopShop uses session-based authentication // This example assumes you've authenticated first const response = await axios.get( `${FOODCOOPSHOP_URL}/admin/members/view/${memberId}.json`, { withCredentials: true, headers: { 'Content-Type': 'application/json', } } );
const member = response.data.member; console.log(`Member: ${member.firstname} ${member.lastname}`); console.log(`Current Balance: €${member.credit_balance}`); console.log(`Status: ${member.active ? 'Active' : 'Inactive'}`);
return member; } catch (error) { console.error('Error fetching member data:', error.message); }}
// UsagecheckMemberBalance(123);Production Best Practices
Security Recommendations
- Strong Passwords: Use strong, unique passwords for MySQL database and admin accounts
- Security Salt: Generate a secure random string for
SECURITY_SALT(never reuse across environments) - Environment Variables: Store all credentials as environment variables, never in code
- HTTPS Only: Klutch.sh provides automatic HTTPS - ensure all links use
https:// - Regular Backups: Implement automated database backups (see Database Backups section)
- Session Security: Configure secure session settings with appropriate timeouts
- File Upload Limits: Set reasonable file size limits to prevent abuse
- Admin Access: Use strong passwords and consider IP restrictions for admin accounts
- Email Security: Use TLS/SSL for SMTP connections to protect credentials
- Database Security: Use least-privilege database accounts with only necessary permissions
Performance Optimization
- PHP OPcache: The official image includes OPcache enabled by default for better PHP performance
- Database Indexing: Ensure proper database indexes on frequently queried columns
- Image Optimization: Compress product images before uploading (recommended max 1MB per image)
- Caching: FoodCoopShop uses CakePHP’s built-in caching - ensure
/tmpvolume has adequate space - Resource Allocation: Monitor CPU and memory usage, scale resources as needed
- Database Connection Pooling: Use persistent database connections (configured by default)
- CDN for Images: Consider using a CDN for serving product images to reduce load
- Session Storage: Consider using database-backed sessions for multi-instance deployments
Database Backup Strategy
Implement a comprehensive backup strategy for your MySQL database:
#!/bin/bash# Example: Automated MySQL backup script# Run this via cron job or scheduled task
DATE=$(date +%Y%m%d_%H%M%S)BACKUP_DIR="/backups/mysql"DB_HOST="${DATABASE_HOST}"DB_PORT="${DATABASE_PORT}"DB_NAME="${DATABASE_NAME}"DB_USER="${DATABASE_USER}"DB_PASS="${DATABASE_PASSWORD}"
# Create backup directorymkdir -p $BACKUP_DIR
# Dump databasemysqldump -h $DB_HOST \ -P $DB_PORT \ -u $DB_USER \ -p$DB_PASS \ --single-transaction \ --routines \ --triggers \ $DB_NAME | gzip > $BACKUP_DIR/foodcoopshop_$DATE.sql.gz
# Keep only last 30 days of backupsfind $BACKUP_DIR -name "foodcoopshop_*.sql.gz" -mtime +30 -delete
echo "Backup completed: foodcoopshop_$DATE.sql.gz"Volume Management
Monitor and manage persistent volumes:
- Regular Cleanup: Periodically remove old temporary files from
/tmp - Image Optimization: Compress uploaded images to save space
- Archive Old Data: Archive old orders and invoices to separate storage
- Monitor Usage: Use Klutch.sh dashboard to track volume usage
- Expansion Planning: Plan for volume expansion before reaching capacity
Monitoring
Monitor your FoodCoopShop deployment for:
- Application Health: Check that the web interface loads correctly
- Response Times: Monitor page load times and database query performance
- Error Logs: Review Apache and PHP error logs regularly
- Database Performance: Monitor MySQL slow query log and connection pool
- Disk Usage: Track persistent volume usage on all three mount points
- Memory Usage: Monitor PHP-FPM memory consumption
- Email Delivery: Verify SMTP connections and email delivery success
- User Activity: Track member logins and order patterns
- Payment Processing: Monitor member credit balances and payment tracking
Scaling Considerations
As your food cooperative grows, consider:
- Vertical Scaling: Increase CPU and memory resources for the container
- Database Optimization: Tune MySQL configuration for larger datasets
- Horizontal Scaling: Run multiple FoodCoopShop instances behind a load balancer
- Read Replicas: Configure MySQL read replicas for improved read performance
- Session Management: Use database-backed sessions or Redis for multi-instance deployments
- File Storage: Consider object storage (S3-compatible) for product images
- Caching Layer: Implement Redis or Memcached for additional caching
- Queue System: Use background job processing for email sending and report generation
Troubleshooting
Cannot Access FoodCoopShop
- Verify HTTP traffic type is selected (not TCP)
- Ensure internal port is set to
80 - Check deployment logs in Klutch.sh dashboard for startup errors
- Verify environment variables are correctly set
- Confirm the application has completed its first startup (can take 2-3 minutes)
Database Connection Errors
- Verify MySQL database is running and accessible
- Check
DATABASE_URLformat:mysql://user:password@host:port/database_name - For Klutch.sh MySQL, ensure port is
8000 - Test database connection from another tool (e.g., MySQL Workbench)
- Check MySQL user has appropriate permissions
- Verify firewall rules allow database connections
File Upload Issues
- Check persistent volumes are correctly mounted at all three paths
- Verify volume sizes have adequate free space
- Ensure PHP upload limits are sufficient in Apache config
- Review Apache error logs for permission issues
- Check that directories are writable by the web server user
Email Not Sending
- Verify SMTP credentials are correct
- Test SMTP connection with a tool like
telnetorswaks - Check SMTP port (587 for TLS, 465 for SSL)
- Ensure
EMAIL_FROMis a valid email address - Review PHP mail logs for delivery errors
- Verify your SMTP provider allows the connection from Klutch.sh
Performance Issues
- Monitor CPU and memory usage in Klutch.sh dashboard
- Check MySQL slow query log for unoptimized queries
- Review Apache access logs for high-traffic patterns
- Consider increasing container resources (CPU/RAM)
- Optimize product images (compress before upload)
- Clear CakePHP cache:
rm -rf /var/www/html/tmp/cache/*
Session Timeout Problems
- Check
SESSION_TIMEOUTenvironment variable - Verify
SESSION_COOKIE_TIMEOUTmatches session timeout - Ensure members aren’t accessing from multiple devices simultaneously
- Review PHP session configuration in
custom_config.php
Product Images Not Displaying
- Verify
/var/www/html/webroot/filesvolume is mounted correctly - Check file permissions on uploaded images
- Ensure images are uploaded in supported formats (JPEG, PNG, GIF)
- Review Apache access logs for 404 errors on image requests
- Verify
APP_FULL_BASE_URLis set correctly
Additional Resources
- FoodCoopShop Official Website
- FoodCoopShop Documentation
- English Demo Instance
- German Demo Instance (Deutsch)
- FoodCoopShop GitHub Repository
- FoodCoopShop Users and Success Stories
- FoodCoopShop Docker Hub
- CakePHP 5 Documentation
- Klutch.sh MySQL Deployment Guide
- Klutch.sh Persistent Volumes Guide
- Klutch.sh Networking Guide
- Klutch.sh Deployments Guide
Conclusion
Deploying FoodCoopShop to Klutch.sh provides your food cooperative with a robust, scalable platform for managing online orders, producer relationships, and member accounts. With MySQL database integration, persistent file storage, and automated HTTPS, you have everything needed to run a successful food cooperative. The platform’s cooperative-first design ensures that features like delivery rhythms, cashless payments, and multi-producer support work seamlessly to connect local producers with community members. Your FoodCoopShop deployment is now ready to support sustainable local food systems and strengthen community connections through technology.