| title | CrowdSec Control Migration Guide |
|---|---|
| description | Migration guide for upgrading Charon from environment variable to GUI-controlled CrowdSec configuration. |
Before (v1.x): CrowdSec was controlled by environment variables like CHARON_SECURITY_CROWDSEC_MODE.
After (v2.x): CrowdSec is controlled via the GUI toggle in the Security dashboard, matching how WAF, ACL, and Rate Limiting work.
In version 1.x, CrowdSec had inconsistent control:
- WAF, ACL, Rate Limiting: GUI-controlled via Settings table
- CrowdSec: Environment variable controlled via docker-compose.yml
This created issues:
- ❌ Users had to restart containers to enable/disable CrowdSec
- ❌ GUI toggle didn't actually control the service
- ❌ Console enrollment could fail silently when LAPI wasn't running
- ❌ Inconsistent UX compared to other security features
Version 2.0 makes CrowdSec work like all other security features:
- ✅ Enable/disable via GUI toggle (no container restart)
- ✅ Real-time status visible in dashboard
- ✅ Better integration with Charon's security orchestration
- ✅ Consistent UX across all security features
Check if you have CrowdSec environment variables set:
grep -i "CROWDSEC_MODE" docker-compose.ymlIf you see any of these:
CHARON_SECURITY_CROWDSEC_MODECERBERUS_SECURITY_CROWDSEC_MODECPM_SECURITY_CROWDSEC_MODE
...then you need to migrate.
Edit your docker-compose.yml and remove these lines:
# REMOVE THESE LINES:
- CHARON_SECURITY_CROWDSEC_MODE=local
- CERBERUS_SECURITY_CROWDSEC_MODE=local
- CPM_SECURITY_CROWDSEC_MODE=localAlso remove (if present):
# These are no longer used (external mode removed)
- CERBERUS_SECURITY_CROWDSEC_API_URL=
- CERBERUS_SECURITY_CROWDSEC_API_KEY=Example: Before
services:
charon:
image: ghcr.io/wikid82/charon:latest
environment:
- CHARON_ENV=production
- CHARON_SECURITY_CROWDSEC_MODE=local # ← Remove thisExample: After
services:
charon:
image: ghcr.io/wikid82/charon:latest
environment:
- CHARON_ENV=production
# CrowdSec is now GUI-controlleddocker compose down
docker compose up -d- Open Charon UI (default:
http://localhost:8080) - Navigate to Security in the sidebar
- Find the CrowdSec card
- Toggle the switch to ON
- Wait 10-15 seconds for LAPI to start
- Verify status shows "Active" with a running PID
docker exec charon cscli lapi statusExpected output:
✓ You can successfully interact with Local API (LAPI)
If you see this, migration is complete! ✅
Charon version 2.0 introduced new database tables to support security features like CrowdSec, WAF configurations, and security audit logs. If you're upgrading from version 1.x with persistent data, you need to run migrations to add these tables.
Yes, if:
- ✅ You're upgrading from Charon 1.x to 2.x
- ✅ You're using a persistent volume for
/app/data - ✅ You see "CrowdSec not starting" after upgrade
- ✅ Container logs show:
WARN security tables missing
No, if:
- ❌ This is a fresh installation (tables created automatically)
- ❌ You're not using persistent storage
- ❌ You've already run migrations once
Step 1: Execute Migration Command
docker exec charon /app/charon migrateExpected Output:
{"level":"info","msg":"Running database migrations for security tables...","time":"2025-12-15T..."}
{"level":"info","msg":"Migration completed successfully","time":"2025-12-15T..."}Step 2: Verify Tables Created
docker exec charon sqlite3 /app/data/charon.db ".tables"You should see these tables:
security_configs— Security feature settings (replaces environment variables)security_decisions— CrowdSec blocking decisionssecurity_audits— Security event audit logsecurity_rule_sets— WAF and rate limiting rulescrowdsec_preset_events— CrowdSec Hub preset trackingcrowdsec_console_enrollments— CrowdSec Console enrollment state
Step 3: Restart Container
If you had CrowdSec enabled before the upgrade, restart to apply changes:
docker restart charonCrowdSec will automatically start if it was previously enabled.
Step 4: Verify CrowdSec Status
Wait 15 seconds after restart, then check:
docker exec charon cscli lapi statusExpected Output (if CrowdSec was enabled):
✓ You can successfully interact with Local API (LAPI)
The migration creates empty tables with the correct schema. Your existing data (proxy hosts, certificates, users, etc.) is not modified.
New tables added:
- SecurityConfig: Stores security feature state (on/off)
- SecurityDecision: Tracks CrowdSec blocking decisions
- SecurityAudit: Logs security-related actions
- SecurityRuleSet: Stores WAF rules and rate limits
- CrowdsecPresetEvent: Tracks Hub preset installations
- CrowdsecConsoleEnrollment: Stores Console enrollment tokens
✅ Idempotent: Safe to run multiple times (no duplicates) ✅ Non-destructive: Only adds tables, never deletes data ✅ Fast: Completes in <1 second ✅ No downtime: Container stays running during migration
Cause: You're running an older version of Charon that doesn't include the migrate command.
Solution: Pull the latest image first:
docker compose pull
docker compose up -d
docker exec charon /app/charon migrateCause: Another process is accessing the database.
Solution: Retry in a few seconds:
sleep 5
docker exec charon /app/charon migrateCause: Database file has incorrect permissions.
Solution: Fix ownership (run on host):
sudo chown -R 1000:1000 ./charon-data
docker exec charon /app/charon migrateSee CrowdSec Troubleshooting for detailed diagnostics.
Future versions will detect missing tables on startup and run migrations automatically. For now, manual migration is required when upgrading from version 1.x.
If you were enrolled in CrowdSec Console before migration:
The enrollment data is stored in the database, not in environment variables. Your Console connection should still work after migration.
- Go to Cerberus → CrowdSec in the sidebar
- Check the Console enrollment status
- If it shows "Enrolled" → you're good! ✅
- If it shows "Not Enrolled" but you were enrolled before → see troubleshooting below
If enrollment was incomplete in v1.x (common issue), re-enroll now:
- Ensure CrowdSec is enabled via GUI toggle (see Step 4 above)
- Verify LAPI is running:
docker exec charon cscli lapi status - Go to Cerberus → CrowdSec
- Click Enroll with CrowdSec Console
- Paste your enrollment token from crowdsec.net
- Submit
1. Edit docker-compose.yml
2. docker compose down
3. docker compose up -d
4. Wait for container to restart (30-60 seconds)
5. Hope CrowdSec started correctly
6. Check logs to verify
1. Toggle switch in Security dashboard
2. Wait 10 seconds
3. See "Active" status immediately
| Aspect | Environment Variable (Old) | GUI Toggle (New) |
|---|---|---|
| Enable/Disable | Edit file + restart container | Click toggle |
| Time to apply | 30-60 seconds | 10-15 seconds |
| Status visibility | Check logs | Real-time dashboard |
| Downtime during change | ❌ Yes (container restart) | ✅ No (zero downtime) |
| Consistency with other features | ❌ Different from WAF/ACL | ✅ Same as WAF/ACL |
| Console enrollment requirement | ✅ UI warns if LAPI not running |
Solution:
-
Check container logs:
docker logs charon | grep crowdsec -
Verify config directory exists:
docker exec charon ls -la /app/data/crowdsec/config -
If missing, restart container:
docker compose restart
-
Try toggling again in GUI
Solution:
-
Verify LAPI is running:
docker exec charon cscli lapi status -
If LAPI is not running:
- Toggle CrowdSec OFF in GUI
- Wait 5 seconds
- Toggle CrowdSec ON in GUI
- Wait 15 seconds
- Re-check LAPI status
-
Re-submit enrollment token (same token works)
Not recommended. Environment variable control is deprecated and will be removed in a future version.
If you must:
The legacy environment variables still work in version 2.0 (for backward compatibility), but:
⚠️ They will be removed in version 3.0⚠️ GUI toggle may not reflect actual state⚠️ You'll encounter issues with Console enrollment⚠️ You'll miss out on improved UX and features
Please migrate to GUI control.
Yes! Use the Charon API:
Enable CrowdSec:
curl -X POST http://localhost:8080/api/v1/admin/crowdsec/startDisable CrowdSec:
curl -X POST http://localhost:8080/api/v1/admin/crowdsec/stopCheck status:
curl http://localhost:8080/api/v1/admin/crowdsec/statusSee API Documentation for more details.
If you encounter critical issues after migration, you can temporarily roll back to environment variable control:
-
Add back the environment variable:
environment: - CHARON_SECURITY_CROWDSEC_MODE=local
-
Restart container:
docker compose down docker compose up -d
-
Report the issue:
- GitHub Issues
- Describe what went wrong
- Attach relevant logs
Need help?
- 📖 Full Documentation
- 🛡️ Security Features Guide
- 🐛 CrowdSec Troubleshooting
- 💬 Community Discussions
- 🐛 Report Issues
✅ Remove environment variables from docker-compose.yml ✅ Restart container ✅ Enable CrowdSec via GUI toggle in Security dashboard ✅ Verify LAPI is running ✅ Re-enroll in Console if needed (same token works)
Benefits:
- ⚡ Faster enable/disable (no container restart)
- 👀 Real-time status visibility
- 🎯 Consistent with other security features
- 🛡️ Better Console enrollment reliability
Timeline: Environment variable support will be removed in version 3.0 (estimated 6-12 months).