Minnow

Installing Minnow

Minnow can be installed on any server that supports PHP and MySQL - the same requirements as WordPress. This guide covers fresh installations on a clean server.

Server Requirements

Requirement Minimum Recommended
PHP 8.1+ 8.2+
MySQL 5.7+ 8.0+
MariaDB 10.3+ 10.6+
Web Server Apache 2.4+ or Nginx Nginx

Required PHP Extensions

  • pdo_mysql - Database connectivity
  • json - JSON parsing
  • mbstring - Multibyte string support
  • openssl - Password hashing and encryption
  • fileinfo - File type detection (for uploads)

Recommended PHP Extensions

  • imagick or gd - Image processing
  • zip - Plugin installation
  • curl - External HTTP requests

PHP Configuration

memory_limit = 256M
upload_max_filesize = 64M
post_max_size = 64M
max_execution_time = 300

Quick Install (CLI)

The fastest way to install Minnow is using the CLI installer. This handles downloading, database setup, and admin user creation in one step.

Prerequisites

You need PHP 8.1+ with the zip extension installed to use the CLI installer.

Step 1: Download the CLI

# Download just the CLI tool first
curl -sL https://github.com/minnow-framework/minnow/releases/latest/download/minnow-cli.phar -o minnow
chmod +x minnow

Or if you have an existing Minnow installation, use its CLI:

cd /path/to/minnow/tools/cli
composer install
alias minnow="php bin/minnow"

Step 2: Download Minnow

# Download to current directory
minnow core:download

# Or specify a path
minnow core:download /var/www/mysite

# Download a specific version
minnow core:download --version=1.0.0

Step 3: Run the Installer

cd /var/www/mysite
minnow core:install

The installer will prompt you for:

  • Database host, name, user, and password
  • Site URL and title
  • Admin username, email, and password

It will then:

  1. Create admin/config.php with your settings
  2. Create all database tables
  3. Insert default options and user roles
  4. Create your admin user

Non-Interactive Install

For automated deployments, pass all options on the command line:

minnow core:install \
  --dbhost=localhost \
  --dbname=minnow \
  --dbuser=minnow \
  --dbpass=your_secure_password \
  --dbprefix=minnow_ \
  --url=https://example.com \
  --title="My Site" \
  --admin-user=admin \
  --admin-email=admin@example.com \
  --admin-pass=your_admin_password

Step 4: Configure Web Server

See Apache or Nginx configuration below.

Done!

Visit https://your-domain.com/admin/ to log in.


Manual Installation

If you prefer manual installation or don't have CLI access, follow these steps.

1. Download Minnow

# Clone or download Minnow to your web root
git clone https://github.com/minnow-framework/minnow.git /var/www/minnow

# Or download and extract a release
wget https://github.com/minnow-framework/minnow/releases/latest/download/minnow.zip
unzip minnow.zip -d /var/www/minnow

2. Set Directory Permissions

cd /var/www/minnow

# Web server needs write access to these directories
chmod -R 755 data/
chmod -R 755 admin/

# Ensure uploads directory exists and is writable
mkdir -p data/uploads
chmod -R 775 data/uploads

# If using Apache with mod_php
chown -R www-data:www-data .

# If using Nginx with PHP-FPM
chown -R www-data:www-data .

3. Create the Database

-- Connect to MySQL as root
mysql -u root -p

-- Create database
CREATE DATABASE minnow CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

-- Create user (change password!)
CREATE USER 'minnow'@'localhost' IDENTIFIED BY 'your_secure_password';
GRANT ALL PRIVILEGES ON minnow.* TO 'minnow'@'localhost';
FLUSH PRIVILEGES;

EXIT;

4. Run the Setup Wizard

  1. Open your browser and navigate to https://your-domain.com/admin/
  2. You'll see the Minnow Setup wizard
  3. Enter your database credentials:
    • Database Name: The database you created in step 3
    • Database Username: Your MySQL username
    • Database Password: Your MySQL password
    • Database Host: Usually localhost
    • Table Prefix: Change from minnow_ for added security
  4. Click Connect Database

The setup wizard will:

  • Test your database connection
  • Generate secure authentication keys
  • Create admin/config.php automatically

If the admin directory is not writable, the wizard will display the config content for you to copy manually into admin/config.php.

4b. Manual Configuration (Alternative)

If you prefer to create the config manually, copy admin/config.sample.php to admin/config.php and edit it:

cp admin/config.sample.php admin/config.php
nano admin/config.php  # Edit with your database credentials

Generate secure keys with PHP:

php -r "for(\$i=0;\$i<8;\$i++) echo \"define('KEY_\$i', '\" . base64_encode(random_bytes(64)) . \"');\n\";"

6. Configure Web Server

Apache (.htaccess)

Create .htaccess in your Minnow root:

<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /

# Handle front controller
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>

# Security headers
<IfModule mod_headers.c>
    Header set X-Content-Type-Options "nosniff"
    Header set X-Frame-Options "SAMEORIGIN"
    Header set X-XSS-Protection "1; mode=block"
</IfModule>

# Protect sensitive files
<FilesMatch "^(config\.php|\.git|composer\.(json|lock))">
    Order allow,deny
    Deny from all
</FilesMatch>

Nginx

server {
    listen 80;
    server_name example.com;
    root /var/www/minnow;
    index index.php;

    # Security headers
    add_header X-Content-Type-Options "nosniff" always;
    add_header X-Frame-Options "SAMEORIGIN" always;
    add_header X-XSS-Protection "1; mode=block" always;

    # Handle uploads
    client_max_body_size 64M;

    # Main location - route through front controller
    location / {
        try_files $uri $uri/ /index.php?$args;
    }

    # PHP processing
    location ~ \.php$ {
        fastcgi_pass unix:/var/run/php/php8.2-fpm.sock;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include fastcgi_params;
        fastcgi_read_timeout 300;
    }

    # Block access to sensitive files
    location ~ /\.(git|env) {
        deny all;
    }

    location ~ ^/admin/config\.php$ {
        deny all;
    }

    # Static file caching
    location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2)$ {
        expires 1y;
        add_header Cache-Control "public, immutable";
    }
}

7. Run the Web Installer

After the database is configured (step 4 or 5), you'll automatically see the site installation wizard:

  1. Enter your site details:
    • Site Title: Your website name
    • Username: Admin username (letters, numbers, underscores, hyphens)
    • Email: Admin email address
    • Password: Strong password (auto-generated one provided)
    • Search Engine Visibility: Check to discourage search engines (for development)
  2. Click Install Minnow
  3. Note your admin credentials
  4. Click Log In to access the admin dashboard

Post-Installation

Set Up the CLI

The CLI provides tools for managing users, content, cron jobs, and updates:

cd /var/www/minnow/tools/cli
composer install

# Test the CLI
./bin/minnow list

# Useful commands
./bin/minnow user:list              # List users
./bin/minnow app-password:create admin "My Script"  # Create API credentials
./bin/minnow core:version --check   # Check for updates
./bin/minnow cron:run               # Run scheduled tasks

Add an alias for convenience:

echo 'alias minnow="/var/www/minnow/tools/cli/bin/minnow"' >> ~/.bashrc
source ~/.bashrc

Configure HTTPS (Recommended)

Use Let's Encrypt for free SSL:

# Install certbot
apt install certbot python3-certbot-nginx  # or python3-certbot-apache

# Get certificate
certbot --nginx -d example.com

# Auto-renewal is configured automatically

Set Up Cron (Recommended)

For scheduled tasks like publishing scheduled posts:

# Add to crontab
crontab -e

# Run Minnow cron every 5 minutes
*/5 * * * * cd /var/www/minnow && php tools/cli/bin/minnow cron:run > /dev/null 2>&1

Or use the web-based cron trigger (useful for shared hosting):

# Add a secret token to your config.php
# cron_token=your_secret_token

# Then call via HTTP
curl -s "https://example.com/admin/api/cron.php?token=your_secret_token"

View cron status:

minnow cron:list     # Show registered tasks
minnow cron:history  # View execution history

Directory Structure

After installation, your Minnow directory should look like:

minnow/
├── admin/               # Admin SPA and API
│   ├── api/             # REST API endpoints
│   ├── config.php       # Configuration file (you create this)
│   ├── index.php        # Admin entry point
│   └── vendor/          # Admin PHP dependencies
├── core/                # Minnow Core library
│   ├── Auth/            # Authentication system
│   ├── Database/        # Database layer
│   ├── Entity/          # ORM entities
│   ├── Hook/            # Event system
│   └── Plugin/          # Plugin system
├── data/                # User data (writable)
│   ├── plugins/         # Installed plugins
│   └── uploads/         # Media uploads
├── frontend/            # Public website templates
├── tools/               # CLI and development tools
│   ├── cli/             # Minnow CLI
│   ├── plugin-analyzer/ # WordPress plugin analyzer
│   └── plugin-generator/# YAML plugin generator
├── index.php            # Front controller
└── .htaccess            # Apache rewrite rules

Troubleshooting

"Database connection error"

  • Verify database credentials in admin/config.php
  • Ensure MySQL is running: systemctl status mysql
  • Check if user has proper permissions
  • Try connecting manually: mysql -u minnow -p minnow

"Permission denied" errors

# Fix ownership
chown -R www-data:www-data /var/www/minnow

# Fix permissions
find /var/www/minnow -type d -exec chmod 755 {} \;
find /var/www/minnow -type f -exec chmod 644 {} \;
chmod -R 775 /var/www/minnow/data/uploads

"500 Internal Server Error"

  • Check PHP error logs: tail -f /var/log/php8.2-fpm.log
  • Enable debug mode in config.php
  • Verify PHP version: php -v
  • Check for missing PHP extensions: php -m

Setup wizard doesn't appear

  • Check that you're accessing /admin/ not just /
  • Clear browser cache
  • Check PHP error logs for issues

Site installer doesn't appear (after database setup)

  • Verify admin/config.php exists and has correct database credentials
  • Test database connection manually: mysql -u user -p database_name
  • Check that database tables don't already exist (delete minnow_options table to re-run installer)
  • Clear browser cache

"Headers already sent" error

  • Ensure no whitespace before <?php in config.php
  • Check for BOM (byte order mark) in PHP files
  • Use UTF-8 without BOM encoding

Migrating from WordPress

If you have an existing WordPress site, you can migrate your content:

cd /var/www/minnow/tools/cli
composer install

# Import from WordPress database
./bin/minnow import:wordpress \
  --source="mysql://wp_user:wp_pass@localhost/wordpress_db" \
  --source-prefix="wp_" \
  --uploads=/var/www/wordpress/wp-content/uploads

See the WordPress Migration Guide for detailed instructions.


Upgrading Minnow

Using the CLI (Recommended)

The easiest way to upgrade is with the CLI:

cd /var/www/minnow

# Check for updates
./tools/cli/bin/minnow core:version --check

# Update to latest version
./tools/cli/bin/minnow core:update

# Or skip the confirmation prompt
./tools/cli/bin/minnow core:update -y

The updater automatically preserves:

  • admin/config.php - Your configuration
  • data/ - Uploads, plugins, and user data
  • frontend/ - Your custom templates

Manual Upgrade

If you prefer to upgrade manually:

cd /var/www/minnow

# Backup first!
cp -r . ../minnow-backup

# Pull latest changes (if using git)
git pull origin main

# Or download and extract new release
# Preserve your config.php and data/ directory

# Clear any caches
./tools/cli/bin/minnow cache:clear

Security Recommendations

  1. Use HTTPS - Always use SSL in production
  2. Strong passwords - Use generated passwords, enable 2FA when available
  3. Unique table prefix - Don't use the default minnow_ prefix
  4. Unique auth keys - Generate fresh keys for each installation
  5. File permissions - Keep files at 644, directories at 755
  6. Restrict admin - Consider IP-restricting /admin/ in production
  7. Regular backups - Back up database and data/uploads regularly
  8. Keep updated - Apply security updates promptly

Getting Help