mirror of
https://github.com/usmannasir/cyberpanel.git
synced 2026-01-16 04:22:05 +01:00
Merge pull request #1545 from master3395/v2.5.5-dev
Add export and import functionality for firewall rules
This commit is contained in:
@@ -2050,9 +2050,163 @@ class FirewallManager:
|
||||
final_json = json.dumps(final_dic)
|
||||
return HttpResponse(final_json)
|
||||
|
||||
|
||||
|
||||
|
||||
def exportFirewallRules(self, userID=None):
|
||||
"""
|
||||
Export all custom firewall rules to a JSON file, excluding default CyberPanel rules
|
||||
"""
|
||||
try:
|
||||
currentACL = ACLManager.loadedACL(userID)
|
||||
|
||||
if currentACL['admin'] == 1:
|
||||
pass
|
||||
else:
|
||||
return ACLManager.loadErrorJson('exportStatus', 0)
|
||||
|
||||
# Get all firewall rules
|
||||
rules = FirewallRules.objects.all()
|
||||
|
||||
# Default CyberPanel rules to exclude
|
||||
default_rules = ['CyberPanel Admin', 'SSHCustom']
|
||||
|
||||
# Filter out default rules
|
||||
custom_rules = []
|
||||
for rule in rules:
|
||||
if rule.name not in default_rules:
|
||||
custom_rules.append({
|
||||
'name': rule.name,
|
||||
'proto': rule.proto,
|
||||
'port': rule.port,
|
||||
'ipAddress': rule.ipAddress
|
||||
})
|
||||
|
||||
# Create export data with metadata
|
||||
export_data = {
|
||||
'version': '1.0',
|
||||
'exported_at': time.strftime('%Y-%m-%d %H:%M:%S'),
|
||||
'total_rules': len(custom_rules),
|
||||
'rules': custom_rules
|
||||
}
|
||||
|
||||
# Create JSON response with file download
|
||||
json_content = json.dumps(export_data, indent=2)
|
||||
|
||||
logging.CyberCPLogFileWriter.writeToFile(f"Firewall rules exported successfully. Total rules: {len(custom_rules)}")
|
||||
|
||||
# Return file as download
|
||||
response = HttpResponse(json_content, content_type='application/json')
|
||||
response['Content-Disposition'] = f'attachment; filename="firewall_rules_export_{int(time.time())}.json"'
|
||||
|
||||
return response
|
||||
|
||||
except BaseException as msg:
|
||||
final_dic = {'exportStatus': 0, 'error_message': str(msg)}
|
||||
final_json = json.dumps(final_dic)
|
||||
return HttpResponse(final_json)
|
||||
|
||||
def importFirewallRules(self, userID=None, data=None):
|
||||
"""
|
||||
Import firewall rules from a JSON file
|
||||
"""
|
||||
try:
|
||||
currentACL = ACLManager.loadedACL(userID)
|
||||
|
||||
if currentACL['admin'] == 1:
|
||||
pass
|
||||
else:
|
||||
return ACLManager.loadErrorJson('importStatus', 0)
|
||||
|
||||
# Handle file upload
|
||||
if hasattr(self.request, 'FILES') and 'import_file' in self.request.FILES:
|
||||
import_file = self.request.FILES['import_file']
|
||||
|
||||
# Read file content
|
||||
import_data = json.loads(import_file.read().decode('utf-8'))
|
||||
else:
|
||||
# Fallback to file path method
|
||||
import_file_path = data.get('import_file_path', '')
|
||||
|
||||
if not import_file_path or not os.path.exists(import_file_path):
|
||||
final_dic = {'importStatus': 0, 'error_message': 'Import file not found or invalid path'}
|
||||
final_json = json.dumps(final_dic)
|
||||
return HttpResponse(final_json)
|
||||
|
||||
# Read and parse the import file
|
||||
with open(import_file_path, 'r') as f:
|
||||
import_data = json.load(f)
|
||||
|
||||
# Validate the import data structure
|
||||
if 'rules' not in import_data:
|
||||
final_dic = {'importStatus': 0, 'error_message': 'Invalid import file format. Missing rules array.'}
|
||||
final_json = json.dumps(final_dic)
|
||||
return HttpResponse(final_json)
|
||||
|
||||
imported_count = 0
|
||||
skipped_count = 0
|
||||
error_count = 0
|
||||
errors = []
|
||||
|
||||
# Default CyberPanel rules to exclude from import
|
||||
default_rules = ['CyberPanel Admin', 'SSHCustom']
|
||||
|
||||
for rule_data in import_data['rules']:
|
||||
try:
|
||||
# Skip default rules
|
||||
if rule_data.get('name', '') in default_rules:
|
||||
skipped_count += 1
|
||||
continue
|
||||
|
||||
# Check if rule already exists
|
||||
existing_rule = FirewallRules.objects.filter(
|
||||
name=rule_data['name'],
|
||||
proto=rule_data['proto'],
|
||||
port=rule_data['port'],
|
||||
ipAddress=rule_data['ipAddress']
|
||||
).first()
|
||||
|
||||
if existing_rule:
|
||||
skipped_count += 1
|
||||
continue
|
||||
|
||||
# Add the rule to the system firewall
|
||||
FirewallUtilities.addRule(
|
||||
rule_data['proto'],
|
||||
rule_data['port'],
|
||||
rule_data['ipAddress']
|
||||
)
|
||||
|
||||
# Add the rule to the database
|
||||
new_rule = FirewallRules(
|
||||
name=rule_data['name'],
|
||||
proto=rule_data['proto'],
|
||||
port=rule_data['port'],
|
||||
ipAddress=rule_data['ipAddress']
|
||||
)
|
||||
new_rule.save()
|
||||
|
||||
imported_count += 1
|
||||
|
||||
except Exception as e:
|
||||
error_count += 1
|
||||
errors.append(f"Rule '{rule_data.get('name', 'Unknown')}': {str(e)}")
|
||||
logging.CyberCPLogFileWriter.writeToFile(f"Error importing rule {rule_data.get('name', 'Unknown')}: {str(e)}")
|
||||
|
||||
logging.CyberCPLogFileWriter.writeToFile(f"Firewall rules import completed. Imported: {imported_count}, Skipped: {skipped_count}, Errors: {error_count}")
|
||||
|
||||
final_dic = {
|
||||
'importStatus': 1,
|
||||
'error_message': "None",
|
||||
'imported_count': imported_count,
|
||||
'skipped_count': skipped_count,
|
||||
'error_count': error_count,
|
||||
'errors': errors
|
||||
}
|
||||
final_json = json.dumps(final_dic)
|
||||
return HttpResponse(final_json)
|
||||
|
||||
except BaseException as msg:
|
||||
final_dic = {'importStatus': 0, 'error_message': str(msg)}
|
||||
final_json = json.dumps(final_dic)
|
||||
return HttpResponse(final_json)
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -2549,4 +2549,151 @@ app.controller('litespeed_ent_conf', function ($scope, $http, $timeout, $window)
|
||||
});
|
||||
};
|
||||
|
||||
// Export/Import Firewall Rules Functions
|
||||
$scope.exportRules = function () {
|
||||
$scope.rulesLoading = false;
|
||||
$scope.actionFailed = true;
|
||||
$scope.actionSuccess = true;
|
||||
|
||||
url = "/firewall/exportFirewallRules";
|
||||
|
||||
var data = {};
|
||||
|
||||
var config = {
|
||||
headers: {
|
||||
'X-CSRFToken': getCookie('csrftoken')
|
||||
}
|
||||
};
|
||||
|
||||
$http.post(url, data, config).then(exportSuccess, exportError);
|
||||
|
||||
function exportSuccess(response) {
|
||||
$scope.rulesLoading = true;
|
||||
|
||||
// Check if response is JSON (error) or file download
|
||||
if (typeof response.data === 'string' && response.data.includes('{')) {
|
||||
try {
|
||||
var errorData = JSON.parse(response.data);
|
||||
if (errorData.exportStatus === 0) {
|
||||
$scope.actionFailed = false;
|
||||
$scope.actionSuccess = true;
|
||||
$scope.errorMessage = errorData.error_message;
|
||||
return;
|
||||
}
|
||||
} catch (e) {
|
||||
// If not JSON, assume it's the file content
|
||||
}
|
||||
}
|
||||
|
||||
// If we get here, it's a successful file download
|
||||
$scope.actionFailed = true;
|
||||
$scope.actionSuccess = false;
|
||||
}
|
||||
|
||||
function exportError(response) {
|
||||
$scope.rulesLoading = true;
|
||||
$scope.actionFailed = false;
|
||||
$scope.actionSuccess = true;
|
||||
$scope.errorMessage = "Could not connect to server. Please refresh this page.";
|
||||
}
|
||||
};
|
||||
|
||||
$scope.importRules = function () {
|
||||
// Create file input element
|
||||
var input = document.createElement('input');
|
||||
input.type = 'file';
|
||||
input.accept = '.json';
|
||||
input.style.display = 'none';
|
||||
|
||||
input.onchange = function(event) {
|
||||
var file = event.target.files[0];
|
||||
if (file) {
|
||||
var reader = new FileReader();
|
||||
reader.onload = function(e) {
|
||||
try {
|
||||
var importData = JSON.parse(e.target.result);
|
||||
|
||||
// Validate file format
|
||||
if (!importData.rules || !Array.isArray(importData.rules)) {
|
||||
$scope.$apply(function() {
|
||||
$scope.actionFailed = false;
|
||||
$scope.actionSuccess = true;
|
||||
$scope.errorMessage = "Invalid import file format. Please select a valid firewall rules export file.";
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// Upload file to server
|
||||
uploadImportFile(file);
|
||||
} catch (error) {
|
||||
$scope.$apply(function() {
|
||||
$scope.actionFailed = false;
|
||||
$scope.actionSuccess = true;
|
||||
$scope.errorMessage = "Invalid JSON file. Please select a valid firewall rules export file.";
|
||||
});
|
||||
}
|
||||
};
|
||||
reader.readAsText(file);
|
||||
}
|
||||
};
|
||||
|
||||
document.body.appendChild(input);
|
||||
input.click();
|
||||
document.body.removeChild(input);
|
||||
};
|
||||
|
||||
function uploadImportFile(file) {
|
||||
$scope.rulesLoading = false;
|
||||
$scope.actionFailed = true;
|
||||
$scope.actionSuccess = true;
|
||||
|
||||
var formData = new FormData();
|
||||
formData.append('import_file', file);
|
||||
|
||||
var config = {
|
||||
headers: {
|
||||
'X-CSRFToken': getCookie('csrftoken'),
|
||||
'Content-Type': undefined
|
||||
},
|
||||
transformRequest: angular.identity
|
||||
};
|
||||
|
||||
$http.post("/firewall/importFirewallRules", formData, config).then(importSuccess, importError);
|
||||
|
||||
function importSuccess(response) {
|
||||
$scope.rulesLoading = true;
|
||||
|
||||
if (response.data.importStatus === 1) {
|
||||
$scope.actionFailed = true;
|
||||
$scope.actionSuccess = false;
|
||||
|
||||
// Refresh rules list
|
||||
populateCurrentRecords();
|
||||
|
||||
// Show import summary
|
||||
var summary = `Import completed successfully!\n` +
|
||||
`Imported: ${response.data.imported_count} rules\n` +
|
||||
`Skipped: ${response.data.skipped_count} rules\n` +
|
||||
`Errors: ${response.data.error_count} rules`;
|
||||
|
||||
if (response.data.errors && response.data.errors.length > 0) {
|
||||
summary += `\n\nErrors:\n${response.data.errors.join('\n')}`;
|
||||
}
|
||||
|
||||
alert(summary);
|
||||
} else {
|
||||
$scope.actionFailed = false;
|
||||
$scope.actionSuccess = true;
|
||||
$scope.errorMessage = response.data.error_message;
|
||||
}
|
||||
}
|
||||
|
||||
function importError(response) {
|
||||
$scope.rulesLoading = true;
|
||||
$scope.actionFailed = false;
|
||||
$scope.actionSuccess = true;
|
||||
$scope.errorMessage = "Could not connect to server. Please refresh this page.";
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
@@ -445,6 +445,41 @@
|
||||
color: var(--text-muted, #64748b);
|
||||
}
|
||||
|
||||
/* Export/Import Buttons */
|
||||
.export-import-buttons {
|
||||
display: flex;
|
||||
gap: 0.75rem;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.btn-export, .btn-import {
|
||||
padding: 0.5rem 1rem;
|
||||
border-radius: 8px;
|
||||
font-weight: 500;
|
||||
font-size: 0.875rem;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
border: none;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
background: rgba(255, 255, 255, 0.2);
|
||||
color: var(--text-light, white);
|
||||
backdrop-filter: blur(10px);
|
||||
}
|
||||
|
||||
.btn-export:hover, .btn-import:hover {
|
||||
background: rgba(255, 255, 255, 0.3);
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
.btn-export:disabled, .btn-import:disabled {
|
||||
opacity: 0.5;
|
||||
cursor: not-allowed;
|
||||
transform: none;
|
||||
}
|
||||
|
||||
.alert {
|
||||
padding: 1rem 1.5rem;
|
||||
border-radius: 8px;
|
||||
@@ -877,7 +912,25 @@
|
||||
</div>
|
||||
{% trans "Firewall Rules" %}
|
||||
</div>
|
||||
<div ng-show="rulesLoading" class="loading-spinner"></div>
|
||||
<div style="display: flex; align-items: center; gap: 1rem;">
|
||||
<div ng-show="rulesLoading" class="loading-spinner"></div>
|
||||
<div class="export-import-buttons">
|
||||
<button type="button"
|
||||
ng-click="exportRules()"
|
||||
class="btn-export"
|
||||
ng-disabled="rulesLoading">
|
||||
<i class="fas fa-download"></i>
|
||||
{% trans "Export Rules" %}
|
||||
</button>
|
||||
<button type="button"
|
||||
ng-click="importRules()"
|
||||
class="btn-import"
|
||||
ng-disabled="rulesLoading">
|
||||
<i class="fas fa-upload"></i>
|
||||
{% trans "Import Rules" %}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Add Rule Section -->
|
||||
|
||||
@@ -63,4 +63,8 @@ urlpatterns = [
|
||||
path('litespeed_ent_conf', views.litespeed_ent_conf, name='litespeed_ent_conf'),
|
||||
path('fetchlitespeed_conf', views.fetchlitespeed_conf, name='fetchlitespeed_conf'),
|
||||
path('saveLitespeed_conf', views.saveLitespeed_conf, name='saveLitespeed_conf'),
|
||||
|
||||
# Firewall Export/Import
|
||||
path('exportFirewallRules', views.exportFirewallRules, name='exportFirewallRules'),
|
||||
path('importFirewallRules', views.importFirewallRules, name='importFirewallRules'),
|
||||
]
|
||||
|
||||
@@ -679,5 +679,29 @@ def deleteBannedIP(request):
|
||||
userID = request.session['userID']
|
||||
fm = FirewallManager()
|
||||
return fm.deleteBannedIP(userID, json.loads(request.body))
|
||||
except KeyError:
|
||||
return redirect(loadLoginPage)
|
||||
|
||||
|
||||
def exportFirewallRules(request):
|
||||
try:
|
||||
userID = request.session['userID']
|
||||
fm = FirewallManager()
|
||||
return fm.exportFirewallRules(userID)
|
||||
except KeyError:
|
||||
return redirect(loadLoginPage)
|
||||
|
||||
|
||||
def importFirewallRules(request):
|
||||
try:
|
||||
userID = request.session['userID']
|
||||
fm = FirewallManager(request)
|
||||
|
||||
# Handle file upload
|
||||
if request.method == 'POST' and 'import_file' in request.FILES:
|
||||
return fm.importFirewallRules(userID, None)
|
||||
else:
|
||||
# Handle JSON data
|
||||
return fm.importFirewallRules(userID, json.loads(request.body))
|
||||
except KeyError:
|
||||
return redirect(loadLoginPage)
|
||||
121
guides/EXPORT_IMPORT_FIREWALL_RULES.md
Normal file
121
guides/EXPORT_IMPORT_FIREWALL_RULES.md
Normal file
@@ -0,0 +1,121 @@
|
||||
# Firewall Rules Export/Import Feature
|
||||
|
||||
## Overview
|
||||
|
||||
This feature allows CyberPanel administrators to export and import firewall rules between servers, making it easy to replicate security configurations across multiple servers.
|
||||
|
||||
## Features
|
||||
|
||||
### Export Functionality
|
||||
- Exports all custom firewall rules to a JSON file
|
||||
- Excludes default CyberPanel rules (CyberPanel Admin, SSHCustom) to prevent conflicts
|
||||
- Includes metadata such as export timestamp and rule count
|
||||
- Downloads file directly to the user's browser
|
||||
|
||||
### Import Functionality
|
||||
- Imports firewall rules from a previously exported JSON file
|
||||
- Validates file format before processing
|
||||
- Skips duplicate rules (same name, protocol, port, and IP address)
|
||||
- Excludes default CyberPanel rules from import
|
||||
- Provides detailed import summary (imported, skipped, error counts)
|
||||
- Shows specific error messages for failed imports
|
||||
|
||||
## Usage
|
||||
|
||||
### Exporting Rules
|
||||
1. Navigate to the Firewall section in CyberPanel
|
||||
2. Click the "Export Rules" button in the Firewall Rules panel header
|
||||
3. The system will generate and download a JSON file containing your custom rules
|
||||
|
||||
### Importing Rules
|
||||
1. Navigate to the Firewall section in CyberPanel
|
||||
2. Click the "Import Rules" button in the Firewall Rules panel header
|
||||
3. Select a previously exported JSON file
|
||||
4. The system will process the import and show a summary of results
|
||||
|
||||
## File Format
|
||||
|
||||
The exported JSON file has the following structure:
|
||||
|
||||
```json
|
||||
{
|
||||
"version": "1.0",
|
||||
"exported_at": "2024-01-15 14:30:25",
|
||||
"total_rules": 5,
|
||||
"rules": [
|
||||
{
|
||||
"name": "Custom Web Server",
|
||||
"proto": "tcp",
|
||||
"port": "8080",
|
||||
"ipAddress": "0.0.0.0/0"
|
||||
},
|
||||
{
|
||||
"name": "Database Access",
|
||||
"proto": "tcp",
|
||||
"port": "3306",
|
||||
"ipAddress": "192.168.1.0/24"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## Security Considerations
|
||||
|
||||
- Only administrators can export/import firewall rules
|
||||
- Default CyberPanel rules are excluded to prevent system conflicts
|
||||
- Import process validates file format and rule data
|
||||
- Failed imports are logged for troubleshooting
|
||||
- Duplicate rules are automatically skipped
|
||||
|
||||
## Error Handling
|
||||
|
||||
The system provides comprehensive error handling:
|
||||
- Invalid file format detection
|
||||
- Missing required fields validation
|
||||
- Individual rule import error tracking
|
||||
- Detailed error messages for troubleshooting
|
||||
- Import summary with counts of successful, skipped, and failed imports
|
||||
|
||||
## Technical Implementation
|
||||
|
||||
### Backend Components
|
||||
- `exportFirewallRules()` method in `FirewallManager`
|
||||
- `importFirewallRules()` method in `FirewallManager`
|
||||
- New URL patterns for export/import endpoints
|
||||
- File upload handling for import functionality
|
||||
|
||||
### Frontend Components
|
||||
- Export/Import buttons in firewall UI
|
||||
- File download handling for exports
|
||||
- File upload dialog for imports
|
||||
- Progress indicators and error messaging
|
||||
- Import summary display
|
||||
|
||||
### Database Integration
|
||||
- Uses existing `FirewallRules` model
|
||||
- Maintains referential integrity
|
||||
- Preserves rule relationships and constraints
|
||||
|
||||
## Benefits
|
||||
|
||||
1. **Time Efficiency**: Significantly reduces time to replicate firewall rules across servers
|
||||
2. **Error Reduction**: Minimizes human error in manual rule creation
|
||||
3. **Consistency**: Ensures identical security policies across multiple servers
|
||||
4. **Backup**: Provides a way to backup and restore firewall configurations
|
||||
5. **Migration**: Simplifies server migration and setup processes
|
||||
|
||||
## Compatibility
|
||||
|
||||
- Compatible with CyberPanel's existing firewall system
|
||||
- Works with both TCP and UDP protocols
|
||||
- Supports all IP address formats (single IPs, CIDR ranges)
|
||||
- Maintains compatibility with existing firewall utilities
|
||||
|
||||
## Future Enhancements
|
||||
|
||||
Potential future improvements could include:
|
||||
- Rule conflict detection and resolution
|
||||
- Selective rule import (choose specific rules)
|
||||
- Rule templates and presets
|
||||
- Bulk rule management
|
||||
- Integration with configuration management tools
|
||||
193
guides/SECURITY_INSTALLATION.md
Normal file
193
guides/SECURITY_INSTALLATION.md
Normal file
@@ -0,0 +1,193 @@
|
||||
# CyberPanel Secure Installation Guide
|
||||
|
||||
## Overview
|
||||
|
||||
This document describes the secure installation process for CyberPanel that eliminates hardcoded passwords and implements environment-based configuration.
|
||||
|
||||
## Security Improvements
|
||||
|
||||
### ✅ **Fixed Security Vulnerabilities**
|
||||
|
||||
1. **Hardcoded Database Passwords** - Now generated securely during installation
|
||||
2. **Hardcoded Django Secret Key** - Now generated using cryptographically secure random generation
|
||||
3. **Environment Variables** - All sensitive configuration moved to `.env` file
|
||||
4. **File Permissions** - `.env` file set to 600 (owner read/write only)
|
||||
|
||||
### 🔐 **Security Features**
|
||||
|
||||
- **Cryptographically Secure Passwords**: Uses Python's `secrets` module for password generation
|
||||
- **Environment-based Configuration**: Sensitive data stored in `.env` file, not in code
|
||||
- **Secure File Permissions**: Environment files protected with 600 permissions
|
||||
- **Credential Backup**: Automatic backup of credentials for recovery
|
||||
- **Fallback Security**: Maintains backward compatibility with fallback method
|
||||
|
||||
## Installation Process
|
||||
|
||||
### 1. **Automatic Secure Installation**
|
||||
|
||||
The installation script now automatically:
|
||||
|
||||
1. Generates secure random passwords for:
|
||||
- MySQL root user
|
||||
- CyberPanel database user
|
||||
- Django secret key
|
||||
|
||||
2. Creates `.env` file with secure configuration:
|
||||
```bash
|
||||
# Generated during installation
|
||||
SECRET_KEY=your_64_character_secure_key
|
||||
DB_PASSWORD=your_24_character_secure_password
|
||||
ROOT_DB_PASSWORD=your_24_character_secure_password
|
||||
```
|
||||
|
||||
3. Creates `.env.backup` file for credential recovery
|
||||
4. Sets secure file permissions (600) on all environment files
|
||||
|
||||
### 2. **Manual Installation** (if needed)
|
||||
|
||||
If you need to manually generate environment configuration:
|
||||
|
||||
```bash
|
||||
cd /usr/local/CyberCP
|
||||
python install/env_generator.py /usr/local/CyberCP
|
||||
```
|
||||
|
||||
## File Structure
|
||||
|
||||
```
|
||||
/usr/local/CyberCP/
|
||||
├── .env # Main environment configuration (600 permissions)
|
||||
├── .env.backup # Credential backup (600 permissions)
|
||||
├── .env.template # Template for manual configuration
|
||||
├── .gitignore # Prevents .env files from being committed
|
||||
└── CyberCP/
|
||||
└── settings.py # Updated to use environment variables
|
||||
```
|
||||
|
||||
## Security Best Practices
|
||||
|
||||
### ✅ **Do's**
|
||||
|
||||
- Keep `.env` and `.env.backup` files secure
|
||||
- Record credentials from `.env.backup` and delete the file after installation
|
||||
- Use strong, unique passwords for production deployments
|
||||
- Regularly rotate database passwords
|
||||
- Monitor access to environment files
|
||||
|
||||
### ❌ **Don'ts**
|
||||
|
||||
- Never commit `.env` files to version control
|
||||
- Don't share `.env` files via insecure channels
|
||||
- Don't use default passwords in production
|
||||
- Don't leave `.env.backup` files on the system after recording credentials
|
||||
|
||||
## Recovery
|
||||
|
||||
### **Lost Credentials**
|
||||
|
||||
If you lose your database credentials:
|
||||
|
||||
1. Check if `.env.backup` file exists:
|
||||
```bash
|
||||
sudo cat /usr/local/CyberCP/.env.backup
|
||||
```
|
||||
|
||||
2. If backup doesn't exist, you'll need to reset MySQL passwords using MySQL recovery procedures
|
||||
|
||||
### **Regenerate Environment**
|
||||
|
||||
To regenerate environment configuration:
|
||||
|
||||
```bash
|
||||
cd /usr/local/CyberCP
|
||||
sudo python install/env_generator.py /usr/local/CyberCP
|
||||
```
|
||||
|
||||
## Configuration Options
|
||||
|
||||
### **Environment Variables**
|
||||
|
||||
| Variable | Description | Default |
|
||||
|----------|-------------|---------|
|
||||
| `SECRET_KEY` | Django secret key | Generated (64 chars) |
|
||||
| `DB_PASSWORD` | CyberPanel DB password | Generated (24 chars) |
|
||||
| `ROOT_DB_PASSWORD` | MySQL root password | Generated (24 chars) |
|
||||
| `DEBUG` | Debug mode | False |
|
||||
| `ALLOWED_HOSTS` | Allowed hosts | localhost,127.0.0.1,hostname |
|
||||
|
||||
### **Custom Configuration**
|
||||
|
||||
To use custom passwords during installation:
|
||||
|
||||
```bash
|
||||
python install/env_generator.py /usr/local/CyberCP "your_root_password" "your_db_password"
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### **Installation Fails**
|
||||
|
||||
If the new secure installation fails:
|
||||
|
||||
1. Check installation logs for error messages
|
||||
2. The system will automatically fallback to the original installation method
|
||||
3. Verify Python dependencies are installed:
|
||||
```bash
|
||||
pip install python-dotenv
|
||||
```
|
||||
|
||||
### **Environment Loading Issues**
|
||||
|
||||
If Django can't load environment variables:
|
||||
|
||||
1. Ensure `.env` file exists and has correct permissions:
|
||||
```bash
|
||||
ls -la /usr/local/CyberCP/.env
|
||||
# Should show: -rw------- 1 root root
|
||||
```
|
||||
|
||||
2. Install python-dotenv if missing:
|
||||
```bash
|
||||
pip install python-dotenv
|
||||
```
|
||||
|
||||
## Migration from Old Installation
|
||||
|
||||
### **Existing Installations**
|
||||
|
||||
For existing CyberPanel installations with hardcoded passwords:
|
||||
|
||||
1. **Backup current configuration**:
|
||||
```bash
|
||||
cp /usr/local/CyberCP/CyberCP/settings.py /usr/local/CyberCP/CyberCP/settings.py.backup
|
||||
```
|
||||
|
||||
2. **Generate new environment configuration**:
|
||||
```bash
|
||||
cd /usr/local/CyberCP
|
||||
python install/env_generator.py /usr/local/CyberCP
|
||||
```
|
||||
|
||||
3. **Update settings.py** (already done in new installations):
|
||||
- The settings.py file now supports environment variables
|
||||
- It will fallback to hardcoded values if .env is not available
|
||||
|
||||
4. **Test the configuration**:
|
||||
```bash
|
||||
cd /usr/local/CyberCP
|
||||
python manage.py check
|
||||
```
|
||||
|
||||
## Support
|
||||
|
||||
For issues with the secure installation:
|
||||
|
||||
1. Check the installation logs
|
||||
2. Verify file permissions
|
||||
3. Ensure all dependencies are installed
|
||||
4. Review the fallback installation method if needed
|
||||
|
||||
---
|
||||
|
||||
**Security Notice**: This installation method significantly improves security by eliminating hardcoded credentials. Always ensure proper file permissions and secure handling of environment files.
|
||||
|
||||
Reference in New Issue
Block a user