Deployment Guide
Version: 1.0.0
This guide covers deploying notifito to production using Docker Compose on a single VPS.
Prerequisites
Server Requirements
| Resource | Minimum | Recommended |
|---|---|---|
| CPU | 2 cores | 4 cores |
| RAM | 4 GB | 8 GB |
| Storage | 20 GB | 50 GB |
| OS | Ubuntu 22.04+ | Ubuntu 24.04 |
Software Requirements
- Docker 29+
- Docker Compose v5
- Domain name with DNS access
Step 1: Server Setup
Create a VPS
DigitalOcean:
# Create a droplet with Ubuntu 24.04
# Recommended: Regular Intel, 4 GB RAM, 2 CPUs
AWS EC2:
# Launch instance with Ubuntu 24.04
# Recommended: t3.medium (2 vCPU, 4 GB RAM)
Linode:
# Create instance with Ubuntu 24.04
# Recommended: Linode 4GB (2 cores, 4 GB RAM)
Initial Server Configuration
# Update system
sudo apt update && sudo apt upgrade -y
# Install Docker
curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh
# Add user to docker group
sudo usermod -aG docker $USER
# Log out and back in, then verify
docker --version
docker compose version
Step 2: Clone Repository
# Clone the repository
git clone https://github.com/turkerince/notifito.git
cd notifito
# Checkout the latest release
git checkout v1.0.0
Step 3: Configure Environment
Create Environment Files
# Copy example environment files
cp apps/core/.env.example apps/core/.env
cp apps/edge/.env.example apps/edge/.env
cp apps/dispatch/.env.example apps/dispatch/.env
cp apps/dashboard/.env.example apps/dashboard/.env
Configure Core Environment
Edit apps/core/.env:
APP_NAME=notifito-core
APP_ENV=production
APP_KEY=base64:generate-a-random-key
APP_DEBUG=false
APP_URL=https://core.yourdomain.com
LOG_CHANNEL=stderr
DB_CONNECTION=pgsql
DB_HOST=postgres
DB_PORT=5432
DB_DATABASE=notifito_core
DB_USERNAME=notifito
DB_PASSWORD=your-secure-database-password
REDIS_HOST=redis
REDIS_PORT=6379
CACHE_STORE=redis
QUEUE_CONNECTION=redis
SESSION_DRIVER=redis
INTERNAL_SECRET=your-internal-secret-key
EDGE_URL=https://edge.yourdomain.com
Configure Edge Environment
Edit apps/edge/.env:
APP_NAME=notifito-edge
APP_ENV=production
APP_KEY=base64:generate-a-random-key
APP_DEBUG=false
APP_URL=https://edge.yourdomain.com
LOG_CHANNEL=stderr
DB_CONNECTION=pgsql
DB_HOST=postgres
DB_PORT=5432
DB_DATABASE=notifito_core
DB_USERNAME=notifito
DB_PASSWORD=your-secure-database-password
REDIS_HOST=redis
REDIS_PORT=6379
CACHE_STORE=redis
QUEUE_CONNECTION=redis
INTERNAL_SECRET=your-internal-secret-key
Configure Dispatch Environment
Edit apps/dispatch/.env:
APP_NAME=notifito-dispatch
APP_ENV=production
APP_KEY=base64:generate-a-random-key
APP_DEBUG=false
APP_URL=https://dispatch.yourdomain.com
LOG_CHANNEL=stderr
DB_CONNECTION=pgsql
DB_HOST=postgres
DB_PORT=5432
DB_DATABASE=notifito_dispatch
DB_USERNAME=notifito
DB_PASSWORD=your-secure-database-password
REDIS_HOST=redis
REDIS_PORT=6379
CACHE_STORE=redis
QUEUE_CONNECTION=redis
POSTMARK_TOKEN=your-postmark-api-token
POSTMARK_BASE_URL=https://api.postmarkapp.com
Configure Dashboard Environment
Edit apps/dashboard/.env:
APP_NAME=notifito-dashboard
APP_ENV=production
APP_KEY=base64:generate-a-random-key
APP_DEBUG=false
APP_URL=https://app.yourdomain.com
LOG_CHANNEL=stderr
DB_CONNECTION=null
REDIS_HOST=redis
REDIS_PORT=6379
CACHE_STORE=redis
SESSION_DRIVER=redis
QUEUE_CONNECTION=sync
CORE_URL=http://core:8000
EDGE_URL=https://edge.yourdomain.com
INTERNAL_SECRET=your-internal-secret-key
Step 4: Configure DNS
Set up DNS records for your domain:
| Record | Type | Value |
|---|---|---|
edge.yourdomain.com |
A | Your server IP |
app.yourdomain.com |
A | Your server IP |
cdn.yourdomain.com |
A | Your server IP |
Example for DigitalOcean:
edge.notifito.com A 123.456.789.0
app.notifito.com A 123.456.789.0
cdn.notifito.com A 123.456.789.0
Step 5: Configure Caddy
Edit docker/caddy/Caddyfile:
{
auto_https on
admin off
}
edge.notifito.com {
reverse_proxy edge:8000
}
app.notifito.com {
reverse_proxy dashboard:8000
}
cdn.notifito.com {
root * /srv/widget
header Cache-Control "public, max-age=300"
header Access-Control-Allow-Origin "*"
file_server
}
Step 6: Build and Deploy
Build Docker Images
# Build all services
docker compose build
Start Services
# Start all services
docker compose up -d
# Check status
docker compose ps
Run Migrations
# Run core migrations
./bin/artisan core migrate --force
# Run dispatch migrations
./bin/artisan dispatch migrate --force
Generate Application Keys
# Generate keys for each app
./bin/artisan core key:generate
./bin/artisan edge key:generate
./bin/artisan dispatch key:generate
./bin/artisan dashboard key:generate
Step 7: Seed Initial Data
Create Admin User
# Access core tinker
./bin/artisan core tinker
# Create tenant and user
$tenant = App\Models\Tenant::create([
'name' => 'Your Company',
'slug' => 'your-company',
'timezone' => 'UTC',
'domains' => ['yourdomain.com'],
'from_name' => 'Your Company',
'from_email' => 'notifications@yourdomain.com',
]);
$user = App\Models\User::create([
'tenant_id' => $tenant->id,
'name' => 'Admin',
'email' => 'admin@yourdomain.com',
'password' => Hash::make('your-secure-password'),
]);
$keys = app(App\Domain\Tenancy\ApiKeyFactory::class);
$keys->issue($tenant, 'Widget', App\Domain\Tenancy\ApiKeyKind::Publishable);
$keys->issue($tenant, 'Push', App\Domain\Tenancy\ApiKeyKind::Secret);
Step 8: Verify Deployment
Run Smoke Test
# Run the smoke deployment test
./bin/smoke-deploy
Expected output:
edge is public through caddy OK
dashboard is public through caddy OK
widget bundle is served by caddy OK
core is NOT public through caddy OK
dispatch is NOT public through caddy OK
core horizon is running OK
dispatch horizon is running OK
Test Endpoints
# Test edge health
curl https://edge.notifito.com/health
# Test dashboard
curl https://app.notifito.com/health
# Test widget schema
curl "https://edge.notifito.com/v1/widget/schema?key=your-publishable-key&item_type=sneaker"
Cloud Deployment Variants
DigitalOcean Droplet
# 1. Create droplet
doctl compute droplet create notifito \
--region nyc1 \
--size s-2vcpu-4gb \
--image ubuntu-24-04-x64 \
--ssh-keys your-ssh-key-id
# 2. SSH into droplet
ssh root@your-droplet-ip
# 3. Follow deployment steps above
AWS EC2
# 1. Launch EC2 instance
aws ec2 run-instances \
--image-id ami-0c55b159cbfafe1f0 \
--instance-type t3.medium \
--key-name your-key-pair \
--security-group-ids sg-xxxxxxxx
# 2. Configure security groups
# Allow: SSH (22), HTTP (80), HTTPS (443)
# 3. Set up Elastic IP
aws ec2 allocate-address
aws ec2 associate-address --instance-id i-xxxxxxxx --allocation-id eipalloc-xxxxxxxx
# 4. Configure Route 53
# Create A records pointing to Elastic IP
# 5. SSH into instance
ssh -i your-key.pem ubuntu@your-instance-ip
# 6. Follow deployment steps above
Linode
# 1. Create Linode
linode-cli linodes create \
--type g6-standard-2 \
--region us-east \
--image linode/ubuntu24.04 \
--authorized_keys your-ssh-key
# 2. SSH into Linode
ssh root@your-linode-ip
# 3. Follow deployment steps above
SSL/TLS Configuration
Caddy automatically handles SSL/TLS with Let's Encrypt. No additional configuration needed.
Verify SSL
# Check certificate
curl -vI https://edge.notifito.com 2>&1 | grep -i "issuer"
Custom SSL Certificates
If you need custom certificates:
edge.notifito.com {
tls /path/to/cert.pem /path/to/key.pem
reverse_proxy edge:8000
}
Monitoring
View Logs
# View all logs
docker compose logs -f
# View specific service logs
docker compose logs -f core
docker compose logs -f edge
docker compose logs -f dispatch
docker compose logs -f dashboard
# View Horizon logs
docker compose logs -f core-horizon
docker compose logs -f dispatch-horizon
Check Service Status
# Check all services
docker compose ps
# Check specific service
docker compose ps core
Monitor Queues
Access Horizon dashboards:
- Core: http://your-server-ip:8001/horizon (internal only)
- Dispatch: http://your-server-ip:8003/horizon (internal only)
Backup Strategy
Database Backup
# Create backup script
cat > /opt/notifito/backup.sh << 'EOF'
#!/bin/bash
BACKUP_DIR="/opt/notifito/backups"
DATE=$(date +%Y%m%d_%H%M%S)
# Backup core database
docker compose exec -T postgres pg_dump -U notifito notifito_core | gzip > "$BACKUP_DIR/core_$DATE.sql.gz"
# Backup dispatch database
docker compose exec -T postgres pg_dump -U notifito notifito_dispatch | gzip > "$BACKUP_DIR/dispatch_$DATE.sql.gz"
# Keep last 7 days
find $BACKUP_DIR -name "*.sql.gz" -mtime +7 -delete
EOF
chmod +x /opt/notifito/backup.sh
# Add to crontab
echo "0 2 * * * /opt/notifito/backup.sh" | crontab -
Restore from Backup
# Restore core database
gunzip -c /opt/notifito/backups/core_20260828_020000.sql.gz | docker compose exec -T postgres psql -U notifito notifito_core
# Restore dispatch database
gunzip -c /opt/notifito/backups/dispatch_20260828_020000.sql.gz | docker compose exec -T postgres psql -U notifito notifito_dispatch
Security Considerations
Firewall Configuration
# Install UFW
sudo apt install ufw
# Allow SSH
sudo ufw allow ssh
# Allow HTTP/HTTPS
sudo ufw allow 80
sudo ufw allow 443
# Enable firewall
sudo ufw enable
Environment Variables
- Use strong, unique passwords for all services
- Generate random secrets for
INTERNAL_SECRETandAPP_KEY - Never commit
.envfiles to version control - Rotate secrets periodically
Database Security
- Use strong passwords
- Limit database access to application containers
- Enable SSL for database connections in production
Updating
Pull Latest Changes
cd /path/to/notifito
git pull origin main
Rebuild and Restart
# Rebuild images
docker compose build
# Restart services
docker compose down
docker compose up -d
# Run migrations
./bin/artisan core migrate --force
./bin/artisan dispatch migrate --force
Zero-Downtime Updates
For zero-downtime updates, use rolling deployments:
# Update one service at a time
docker compose up -d --no-deps core
docker compose up -d --no-deps edge
docker compose up -d --no-deps dispatch
docker compose up -d --no-deps dashboard
Troubleshooting
Services Not Starting
# Check logs
docker compose logs
# Check specific service
docker compose logs core
# Restart services
docker compose restart
Database Connection Issues
# Check PostgreSQL status
docker compose exec postgres pg_isready
# Check database exists
docker compose exec postgres psql -U notifito -l
Queue Workers Not Processing
# Check Horizon status
docker compose exec core php artisan horizon:status
# Restart Horizon
docker compose restart core-horizon
docker compose restart dispatch-horizon
SSL Certificate Issues
# Check Caddy logs
docker compose logs caddy
# Verify DNS
dig edge.notifito.com
Related Documentation
- Configuration Reference — Environment variables
- Development Setup — Local development
- Architecture Overview — System design