A fresh FreeScout installation is functional but not secure for production. This guide hardens your FreeScout server against common attacks: brute-force login attempts, SQL injection, XSS, DDoS, unauthorized access, and data loss.
Following this guide brings your FreeScout installation to production-grade security.
The Three Layers of Security
- Network Security — Firewall, rate limiting, fail2ban
- Application Security — PHP hardening, input validation, headers
- Data Security — Backups, encryption, access control
Layer 1: Network Security
Step 1: Configure Firewall (UFW)
sudo ufw enable
sudo ufw default deny incoming
sudo ufw default allow outgoing
# Allow SSH (critical!)
sudo ufw allow 22/tcp
# Allow HTTP/HTTPS
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
# Verify rules
sudo ufw status
Output should show:
To Action From
-- ------ ----
22/tcp ALLOW Anywhere
80/tcp ALLOW Anywhere
443/tcp ALLOW Anywhere
Step 2: Configure Fail2Ban (Brute-Force Protection)
Fail2Ban blocks IP addresses that repeatedly fail login attempts.
sudo apt install -y fail2ban
sudo systemctl enable fail2ban
sudo systemctl start fail2ban
Create a custom jail for FreeScout:
sudo nano /etc/fail2ban/jail.local
Add:
[DEFAULT]
bantime = 3600
maxretry = 5
findtime = 600
[sshd]
enabled = true
port = ssh
filter = sshd
logpath = /var/log/auth.log
[recidive]
enabled = true
filter = recidive
action = iptables-multiport[name=recidive, port="http,https"]
logpath = /var/log/fail2ban.log
bantime = 604800
findtime = 86400
maxretry = 5
Restart fail2ban:
sudo systemctl restart fail2ban
Verify it's working:
sudo fail2ban-client status
sudo fail2ban-client status sshd
Step 3: Disable Root SSH Login
sudo nano /etc/ssh/sshd_config
Change:
PermitRootLogin no
PasswordAuthentication no
PubkeyAuthentication yes
X11Forwarding no
Reload SSH:
sudo systemctl reload sshd
From now on, SSH only via key-based auth and non-root user.
Step 4: Rate Limiting on NGINX
Edit your NGINX config:
limit_req_zone $binary_remote_addr zone=general:10m rate=10r/s;
limit_req_zone $binary_remote_addr zone=login:10m rate=5r/m;
server {
location / {
limit_req zone=general burst=20;
# ... rest of config
}
location ~ ^/login {
limit_req zone=login burst=5;
# ... rest of config
}
}
This limits login attempts to 5 per minute per IP.
Reload NGINX:
sudo nginx -t
sudo systemctl reload nginx
Layer 2: Application Security
Step 5: PHP Security Hardening
Edit /etc/php/8.2/fpm/php.ini:
sudo nano /etc/php/8.2/fpm/php.ini
Set:
# Hide PHP version
expose_php = Off
# Disable dangerous functions
disable_functions = exec, passthru, shell_exec, system, proc_open, popen, curl_exec, curl_multi_exec, parse_ini_file, show_source
# Strict error reporting (don't expose errors to users)
display_errors = Off
log_errors = On
error_log = /var/www/freescout/storage/logs/php-error.log
# Session security
session.cookie_httponly = On
session.cookie_secure = On
session.use_only_cookies = On
session.cookie_samesite = Strict
# File upload limits
upload_max_filesize = 100M
post_max_size = 100M
# Memory limits
memory_limit = 256M
max_execution_time = 300
Restart PHP-FPM:
sudo systemctl restart php8.2-fpm
Step 6: NGINX Security Headers
Add to your NGINX config:
server {
# ... existing config ...
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Permissions-Policy "geolocation=(), microphone=(), camera=()" always;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
}
Test and reload:
sudo nginx -t
sudo systemctl reload nginx
Step 7: FreeScout Application Security
In /var/www/freescout/.env:
APP_ENV=production
APP_DEBUG=false
FORCE_HTTPS=true
Never set APP_DEBUG=true in production — it exposes sensitive information.
Step 8: Database User Permissions
Restrict the database user to only what it needs:
sudo mysql -u root -p
-- Remove default access
GRANT USAGE ON *.* TO 'freescout'@'localhost' REQUIRE NONE;
GRANT ALL PRIVILEGES ON freescout.* TO 'freescout'@'localhost';
FLUSH PRIVILEGES;
-- No access from other hosts
DROP USER IF EXISTS 'freescout'@'%';
Layer 3: Data Security
Step 9: Automated Backups
Set up automatic daily backups:
mkdir -p /var/backups/freescout
Create backup script /usr/local/bin/backup-freescout.sh:
#!/bin/bash
BACKUP_DIR="/var/backups/freescout"
DATE=$(date +%Y-%m-%d_%H%M%S)
DB_NAME="freescout"
# Create backup directory if it doesn't exist
mkdir -p $BACKUP_DIR
# Backup database
mysqldump -u freescout -p$DB_PASSWORD $DB_NAME | gzip > $BACKUP_DIR/db_$DATE.sql.gz
# Backup application files
tar -czf $BACKUP_DIR/app_$DATE.tar.gz /var/www/freescout
# Keep only last 30 days of backups
find $BACKUP_DIR -type f -mtime +30 -delete
echo "Backup completed: $DATE"
Make it executable:
sudo chmod +x /usr/local/bin/backup-freescout.sh
Add to crontab:
sudo crontab -e
Add:
0 2 * * * /usr/local/bin/backup-freescout.sh >> /var/log/freescout-backup.log 2>&1
This runs backup at 2 AM daily.
Step 10: Upload Backups to External Storage (Cloud)
For maximum safety, store backups off-server:
# Using AWS S3
sudo apt install -y awscli
# Configure AWS credentials
aws configure
# Add to backup script
aws s3 cp /var/backups/freescout/db_$DATE.sql.gz s3://your-bucket/freescout/
Or use a service like Backblaze, Google Cloud Storage, or DigitalOcean Spaces.
Step 11: File Permissions
Ensure proper file permissions:
cd /var/www/freescout
# Web server owns application
sudo chown -R www-data:www-data .
# Directories: 755, Files: 644
sudo find . -type d -exec chmod 755 {} \;
sudo find . -type f -exec chmod 644 {} \;
# Sensitive directories: 700
sudo chmod 700 storage bootstrap/cache
Step 12: Log Monitoring
Enable log monitoring to detect attacks:
# View access logs
sudo tail -f /var/log/nginx/access.log
# View error logs
sudo tail -f /var/log/nginx/error.log
# View FreeScout logs
sudo tail -f /var/www/freescout/storage/logs/laravel.log
Look for:
- Suspicious IP addresses
- SQL injection attempts (UNION, SELECT, DROP keywords)
- Path traversal attempts (../)
- High 404 or 403 rates
Layer 4: Compliance & Auditing
Step 13: GDPR Compliance Checklist
- ✅ Data Storage: Verify data is stored on your server (not third-party clouds)
- ✅ Encryption: Use HTTPS for all traffic
- ✅ Backups: Store backups securely (encrypted, off-site)
- ✅ Access Control: Limit who can access FreeScout
- ✅ Data Retention: Delete old tickets per your retention policy
- ✅ Privacy Policy: Display privacy policy on your website
- ✅ Consent: Get user consent before storing data
Step 14: Security Audit Checklist
Run this monthly:
# Check SSL certificate validity
echo | openssl s_client -servername your-domain.com -connect your-domain.com:443 2>/dev/null | openssl x509 -noout -dates
# Check for security updates
sudo apt list --upgradable
# Review firewall rules
sudo ufw status
# Check fail2ban status
sudo fail2ban-client status
# Review backup status
ls -lh /var/backups/freescout/
# Check disk space
df -h
# Check MySQL version and updates
mysql --version
Security Incident Response
If you suspect a breach:
Immediate Actions
- Disable compromised users: Settings → Users → disable agent
- Force password reset: Ask all users to reset passwords
- Review logs: Check
/var/log/nginx/access.logfor suspicious activity - Restore from backup: If data is corrupted, restore from a known-good backup
- Update dependencies: Run
composer updateto patch vulnerabilities
Investigation
# Check for backdoors
find /var/www/freescout -name "*.php" -type f -exec grep -l "eval\|system\|shell_exec" {} \;
# Check file timestamps for recently modified files
find /var/www/freescout -type f -mtime -7 -ls
# Check for unauthorized SSH keys
cat /home/freescout/.ssh/authorized_keys
Security Tools
Lynis (Security Audit)
sudo apt install -y lynis
sudo lynis audit system
Generates a report of security issues.
Rkhunter (Rootkit Detection)
sudo apt install -y rkhunter
sudo rkhunter --check --skip-warnings
Detects rootkits and malware.
ClamAV (Antivirus)
sudo apt install -y clamav clamav-daemon
sudo freshclam
sudo clamscan -r /var/www/freescout
Security Checklist (Print & Save)
- [ ] Firewall enabled (ufw)
- [ ] Fail2Ban installed and running
- [ ] SSH key-based auth only (no passwords)
- [ ] Root SSH login disabled
- [ ] PHP hardened (expose_php off, dangerous functions disabled)
- [ ] NGINX security headers enabled
- [ ] HTTPS/SSL configured (Let's Encrypt)
- [ ] APP_DEBUG=false in production
- [ ] Database user restricted to localhost
- [ ] Automated daily backups running
- [ ] Backups uploaded to external storage
- [ ] File permissions set correctly (755 dirs, 644 files)
- [ ] Log monitoring in place
- [ ] Monthly security audit scheduled
- [ ] GDPR compliance verified
Want expert security hardening and compliance review for FreeScout?
We handle the full FreeScout installation on your server — SSL, email, security hardening, and a 1-hour onboarding call. Done in 24 hours.
One-time fee · 30-day support · Money-back guarantee
What Not to Do
- ❌ Don't disable the firewall
- ❌ Don't set APP_DEBUG=true in production
- ❌ Don't reuse passwords across services
- ❌ Don't skip backup testing (verify backups actually work)
- ❌ Don't ignore security updates
- ❌ Don't use weak database passwords
- ❌ Don't expose error messages to users
Next Steps
- Implement layers 1 & 2: Firewall, fail2ban, PHP hardening (today)
- Set up backups: Automated daily backups to cloud (this week)
- Enable monitoring: Log monitoring, security alerts (this week)
- Monthly audits: Run Lynis, review logs, check for updates (every month)
- Incident response plan: Document what to do if breached (now)
A hardened FreeScout is a reliable, secure helpdesk that keeps customer data safe.
Resources
- CIS Ubuntu Benchmark — security hardening standards
- Fail2Ban Documentation — intrusion prevention system
- SSL Labs Server Test — check your SSL configuration grade
- UFW Documentation — Ubuntu firewall management
- OWASP Top 10 — web application security risks