This guide walks you through testing the mail-overrides setup locally with Docker, including the Redis ephemeral sessions plugin.
- Docker and Docker Compose installed
- Git submodules initialized
git submodule update --init --recursiveSnappyMail must be compiled before use:
cd mail
npm install
npx gulp
cd ..This builds the CSS/JS assets. Only needed once (or when updating the mail submodule).
# Make scripts executable
chmod +x scripts/*.sh
# Build dist/ with SnappyMail + overrides
./scripts/build.shThis copies mail/ → dist/ and applies your plugins/themes.
# Build and start containers
docker-compose -f docker/docker-compose.yml up --build
# Or run in detached mode
docker-compose -f docker/docker-compose.yml up -d --buildThis will start:
- SnappyMail on http://localhost:8080 (serving from
dist/) - Redis on localhost:6379
Note: Predis (PHP Redis client) is automatically installed on container startup.
-
Default admin credentials are usually:
- Username:
admin - Password:
12345(change immediately!)
- Username:
-
If this is first setup, you'll need to create admin account
- Go to Plugins tab
- Find ForwardEmail plugin
- Click Enable
- Go to Plugins tab
- Find Redis Ephemeral Sessions plugin
- Click Configure and enter:
| Setting | Value | Notes |
|---|---|---|
| Redis Host | redis-dev |
Docker service name |
| Redis Port | 6379 |
Default Redis port |
| Use TLS | false |
Not needed for local dev |
| Redis Password | (leave empty) | Not set in local Redis |
| Session TTL | 14400 |
4 hours (default) |
| Key Mask Secret | (see below) | Generate with command below |
Generate Key Mask Secret:
openssl rand -base64 32Copy the output and paste it into the "Key Mask Secret" field.
- Click Save then Enable
- Go to Plugins tab
- Find Client IP Passthrough plugin
- Click Enable
Visit http://localhost:8080 - you should see the Forward Email branded login page.
Method 1: Via Redis CLI
# Test Redis is running
docker exec -it snappymail-redis-dev redis-cli ping
# Expected output: PONGMethod 2: Via SnappyMail Plugin API Open browser console on http://localhost:8080 and run:
await fetch('?/Json/&q[]=/0/', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ Action: 'PluginRedisTestConnection' })
}).then(r => r.json()).then(console.log);Expected output:
{
"Result": {
"success": true,
"message": "Redis connection successful"
}
}- Configure an email account (IMAP/SMTP settings)
- Login with credentials
- Check that session is stored in Redis:
# List Redis session keys
docker exec -it snappymail-redis-dev redis-cli KEYS "snappymail:v1:session:*"
# Count active sessions
docker exec -it snappymail-redis-dev redis-cli --scan --pattern "snappymail:v1:session:*" | wc -lThe snappymail-dev-data volume under /var/www/html/data persists SnappyMail’s runtime state (config copies, contacts, sessions). If you need a clean slate (e.g., to reapply defaults or reset CardDAV), run:
docker-compose -f docker/docker-compose.yml down
docker volume rm snappymail-dev-data
docker-compose -f docker/docker-compose.yml up --buildThis removes the runtime configs/ and storage/ copies so SnappyMail re-seeds them from dist/ on the next start.
SnappyMail Logs:
docker logs -f snappymail-local-devRedis Logs:
docker logs -f snappymail-redis-devSnappyMail Application Logs:
# View logs from inside container
docker exec -it snappymail-local-dev cat /var/www/html/data/logs/log-*.txt | grep "REDIS-SESSION"- Edit plugin files in
plugins/directory (NOT inmail/ordist/) - Run build script to rebuild dist/:
./scripts/build.sh
- Restart Docker container:
docker-compose -f docker/docker-compose.yml restart snappymail-dev
- Refresh browser to see changes
Note: The mail/ submodule stays clean - you never edit it directly. The dist/ directory is rebuilt each time you run build.sh.
# Rebuild and restart
docker-compose -f docker/docker-compose.yml up --build
# Or rebuild specific service
docker-compose -f docker/docker-compose.yml build snappymail-dev
docker-compose -f docker/docker-compose.yml up snappymail-dev# Delete all sessions
docker exec -it snappymail-redis-dev redis-cli FLUSHDB
# Delete specific session pattern
docker exec -it snappymail-redis-dev redis-cli --scan --pattern "snappymail:v1:session:*" | xargs docker exec -i snappymail-redis-dev redis-cli DEL# Remove dist/ directory
./scripts/clean.sh
# Rebuild from scratch
./scripts/build.shThe mail submodule needs to be built first:
cd mail
npm install
npx gulp
cd ..
./scripts/build.shPredis should be installed automatically on container startup. If you still see this error:
Solution:
# Check container logs to see if Predis installation failed
docker logs snappymail-local-dev
# Manually install Predis in the container
docker exec -it snappymail-local-dev composer install
# Or restart the container to trigger auto-install
docker-compose -f docker/docker-compose.yml restart snappymail-devCheck Redis is running:
docker ps | grep redis
docker exec -it snappymail-redis-dev redis-cli pingCheck Redis host configuration:
- In SnappyMail admin, verify Redis Host is set to
redis-dev(not127.0.0.1)
Solution:
# Rebuild dist/ with plugins
./scripts/build.sh
# Check plugins directory in dist/
ls -la dist/snappymail/v/0.0.0/plugins/
# Restart container
docker-compose -f docker/docker-compose.yml restart snappymail-devThis happens when accessing SnappyMail over HTTP (not HTTPS).
For local development: Modern browsers allow WebCrypto on localhost even over HTTP, so this shouldn't be an issue.
If still seeing error: Try accessing via https://localhost:8080 (you'll get a cert warning, that's OK for dev).
If port 8080 or 6379 is already in use:
Option 1: Stop conflicting services
# Find what's using the port
lsof -i :8080
lsof -i :6379
# Kill the process or stop the serviceOption 2: Change ports in docker-compose.yml
ports:
- "8081:80" # Change from 8080# Stop containers (preserves data)
docker-compose -f docker/docker-compose.yml stop
# Stop and remove containers (preserves volumes)
docker-compose -f docker/docker-compose.yml down
# Stop and remove everything including volumes (fresh start)
docker-compose -f docker/docker-compose.yml down -v# Watch Redis commands in real-time
docker exec -it snappymail-redis-dev redis-cli MONITOR
# View Redis stats
docker exec -it snappymail-redis-dev redis-cli INFO stats
# View memory usage
docker exec -it snappymail-redis-dev redis-cli INFO memoryBefore deploying to production, verify:
- SnappyMail loads at http://localhost:8080
- Forward Email theme is applied (branded login page)
- All 3 plugins appear in admin panel
- Redis connection test succeeds
- Can login with email credentials
- Session is stored in Redis (check with
KEYScommand) - Session persists across page refreshes
- Session expires after TTL (test with short TTL)
- Logout deletes session from Redis
- No errors in Docker logs
- No errors in SnappyMail application logs
Once local testing is complete:
- Commit changes to
mail-overridesrepository - Update
forwardemail.netmonorepo to pull latestmail-overrides - Deploy with Ansible from main monorepo