Docker & VPS Deployment
Three deployment options: Docker Compose (recommended), VPS manual setup, or shared hosting (cPanel). Choose the one that fits your infrastructure.
Option 1: Docker Compose (Recommended)
The fastest way to deploy MailTrixy. Requires Docker and Docker Compose installed on your server.
Step 1: Clone & Configure
# Upload or clone MailTrixy to your server
cd /opt
unzip mailtrixy.zip -d mailtrixy
cd mailtrixy
# Copy environment file
cp .env.example .env
# Generate application key
php artisan key:generate
Step 2: Create docker-compose.yml
version: '3.8'
services:
app:
build:
context: .
dockerfile: Dockerfile
restart: unless-stopped
volumes:
- .:/var/www/html
- ./storage:/var/www/html/storage
depends_on:
- mysql
environment:
- APP_ENV=production
- APP_DEBUG=false
networks:
- mailtrixy
nginx:
image: nginx:alpine
restart: unless-stopped
ports:
- "80:80"
- "443:443"
volumes:
- .:/var/www/html
- ./docker/nginx.conf:/etc/nginx/conf.d/default.conf
- ./docker/ssl:/etc/nginx/ssl
depends_on:
- app
networks:
- mailtrixy
mysql:
image: mysql:8.0
restart: unless-stopped
environment:
MYSQL_ROOT_PASSWORD: ${DB_PASSWORD}
MYSQL_DATABASE: ${DB_DATABASE}
MYSQL_USER: ${DB_USERNAME}
MYSQL_PASSWORD: ${DB_PASSWORD}
volumes:
- mysql_data:/var/lib/mysql
ports:
- "3306:3306"
networks:
- mailtrixy
scheduler:
build:
context: .
dockerfile: Dockerfile
restart: unless-stopped
command: php artisan schedule:work
volumes:
- .:/var/www/html
depends_on:
- mysql
networks:
- mailtrixy
volumes:
mysql_data:
networks:
mailtrixy:
driver: bridge
Step 3: Create Dockerfile
FROM php:8.2-fpm
# Install system dependencies
RUN apt-get update && apt-get install -y \
git curl zip unzip libpng-dev libjpeg-dev libfreetype6-dev \
libonig-dev libxml2-dev libzip-dev libicu-dev \
&& docker-php-ext-configure gd --with-freetype --with-jpeg \
&& docker-php-ext-install pdo_mysql mbstring exif pcntl bcmath gd zip intl
# Install Composer
COPY --from=composer:latest /usr/bin/composer /usr/bin/composer
# Set working directory
WORKDIR /var/www/html
# Copy application
COPY . .
# Install dependencies
RUN composer install --no-dev --optimize-autoloader
# Set permissions
RUN chown -R www-data:www-data /var/www/html/storage /var/www/html/bootstrap/cache
EXPOSE 9000
CMD ["php-fpm"]
Step 4: Create Nginx Config
# Create docker/nginx.conf
server {
listen 80;
server_name your-domain.com;
root /var/www/html/public;
index index.php;
client_max_body_size 50M;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
fastcgi_pass app:9000;
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
include fastcgi_params;
}
location ~ /\.(?!well-known).* {
deny all;
}
}
Step 5: Deploy
# Build and start containers
docker-compose up -d --build
# Run migrations and seed
docker-compose exec app php artisan migrate --seed
# Generate app key (if not done)
docker-compose exec app php artisan key:generate
# Create storage link
docker-compose exec app php artisan storage:link
# Build frontend assets
docker-compose exec app npm install && npm run build
# Clear caches
docker-compose exec app php artisan config:cache
docker-compose exec app php artisan route:cache
docker-compose exec app php artisan view:cache
Your MailTrixy instance is now running at http://your-domain.com
Option 2: VPS Manual Setup (Ubuntu 22.04)
Step 1: Install System Packages
sudo apt update && sudo apt upgrade -y
# PHP 8.2 + extensions
sudo add-apt-repository ppa:ondrej/php -y
sudo apt install -y php8.2-fpm php8.2-cli php8.2-mysql php8.2-mbstring \
php8.2-xml php8.2-bcmath php8.2-zip php8.2-gd php8.2-curl \
php8.2-intl php8.2-imap
# MySQL 8
sudo apt install -y mysql-server
# Nginx
sudo apt install -y nginx
# Composer
curl -sS https://getcomposer.org/installer | php
sudo mv composer.phar /usr/local/bin/composer
# Node.js 20 (for building frontend)
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
sudo apt install -y nodejs
Step 2: Configure MySQL
sudo mysql -u root
CREATE DATABASE mailtrixy CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'mailtrixy'@'localhost' IDENTIFIED BY 'your_secure_password';
GRANT ALL PRIVILEGES ON mailtrixy.* TO 'mailtrixy'@'localhost';
FLUSH PRIVILEGES;
EXIT;
Step 3: Deploy Application
# Upload MailTrixy to /var/www
cd /var/www
unzip mailtrixy.zip -d mailtrixy
cd mailtrixy
# Set permissions
sudo chown -R www-data:www-data storage bootstrap/cache
sudo chmod -R 775 storage bootstrap/cache
# Install dependencies
composer install --no-dev --optimize-autoloader
npm install && npm run build
# Configure environment
cp .env.example .env
php artisan key:generate
# Edit .env with your database credentials, APP_URL, etc.
nano .env
# Run migrations
php artisan migrate --seed
php artisan storage:link
Step 4: Configure Nginx
sudo nano /etc/nginx/sites-available/mailtrixy
server {
listen 80;
server_name your-domain.com;
root /var/www/mailtrixy/public;
index index.php;
client_max_body_size 50M;
add_header X-Frame-Options "SAMEORIGIN";
add_header X-Content-Type-Options "nosniff";
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
fastcgi_pass unix:/run/php/php8.2-fpm.sock;
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
include fastcgi_params;
}
location ~ /\.(?!well-known).* {
deny all;
}
}
# Enable site
sudo ln -s /etc/nginx/sites-available/mailtrixy /etc/nginx/sites-enabled/
sudo nginx -t && sudo systemctl reload nginx
Step 5: Setup Cron
sudo crontab -u www-data -e
# Add this line:
* * * * * cd /var/www/mailtrixy && php artisan schedule:run >> /dev/null 2>&1
Step 6: SSL with Let's Encrypt
sudo apt install -y certbot python3-certbot-nginx
sudo certbot --nginx -d your-domain.com
# Follow the prompts to complete SSL setup
Option 3: Shared Hosting (cPanel)
- Upload the MailTrixy ZIP to your hosting via File Manager or FTP
- Extract to a directory (e.g.,
/home/user/mailtrixy) - Set document root to
/home/user/mailtrixy/publicin cPanel → Domains - Create MySQL database via cPanel → MySQL Databases
- Edit .env via File Manager — set DB credentials, APP_URL
- Run setup via SSH or the web installer:
cd ~/mailtrixy php artisan key:generate php artisan migrate --seed php artisan storage:link - Setup cron in cPanel → Cron Jobs (run every minute):
cd /home/user/mailtrixy && php artisan schedule:run >> /dev/null 2>&1
Note: MailTrixy works on shared hosting without Redis. It uses database queues and the scheduler processes all background jobs automatically via the single cron job above.
Environment Variables Reference
| Variable | Description | Example |
|---|---|---|
APP_URL | Your domain URL | https://mail.yourdomain.com |
APP_ENV | Environment mode | production |
APP_DEBUG | Debug mode (disable in production!) | false |
DB_HOST | MySQL host | 127.0.0.1 or mysql (Docker) |
DB_DATABASE | Database name | mailtrixy |
DB_USERNAME | Database user | mailtrixy |
DB_PASSWORD | Database password | your_secure_password |
MAIL_MAILER | Mail driver | smtp or log |
QUEUE_CONNECTION | Queue driver | database |
GOOGLE_CLIENT_ID | Gmail OAuth client ID | From Google Cloud Console |
GOOGLE_CLIENT_SECRET | Gmail OAuth secret | From Google Cloud Console |
MICROSOFT_CLIENT_ID | Outlook OAuth client ID | From Azure Portal |
MICROSOFT_CLIENT_SECRET | Outlook OAuth secret | From Azure Portal |
STRIPE_KEY | Stripe publishable key | pk_live_... |
STRIPE_SECRET | Stripe secret key | sk_live_... |
STRIPE_WEBHOOK_SECRET | Stripe webhook signing secret | whsec_... |
Troubleshooting
500 Internal Server Error
- Check
storage/logs/laravel.logfor the actual error - Ensure
storage/andbootstrap/cache/are writable:chmod -R 775 storage bootstrap/cache - Run
php artisan config:clear && php artisan cache:clear
Database Connection Refused
- Verify
.envDB credentials match your MySQL setup - Docker: use
DB_HOST=mysql(service name), not127.0.0.1 - Check MySQL is running:
sudo systemctl status mysql
Styles/CSS Not Loading
- Run
npm run buildto compile assets - Run
php artisan storage:link - Ensure
APP_URLmatches your actual domain
Emails Not Syncing
- Ensure the cron job is running: check
storage/logs/laravel.logfor[Scheduler]entries - For Gmail: use an App Password, not your regular password
- Run manually:
php artisan mailtrixy:sync-emails --force
Queue Jobs Not Processing
- The scheduler handles queue processing automatically via
queue:work --stop-when-empty - Check pending jobs:
php artisan tinker --execute="echo DB::table('jobs')->count();" - Check failed jobs:
php artisan queue:failed