fix: implement persistent Docker volume configuration to prevent data loss

Previously, configuration created via the web UI was lost when containers were
recreated or updated, requiring users to reconfigure each time. This was due to
the .env file being stored inside the container filesystem.

Changes:
- Add persistent volume mount for configuration directory in docker-compose.yml
- Update ConfigApi to auto-detect Docker vs development environment
- Configure dotenv loading to use persistent config path when available
- Update file watcher to monitor correct .env file location
- Remove conflicting host .env file mount
- Update README with new volume configuration instructions

Configuration now persists across container updates, eliminating the need for
users to reconfigure after updates.

Fixes #94

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
courtmanr@gmail.com
2025-05-31 10:30:51 +01:00
parent 7249a2dd13
commit d883d85b7b
5 changed files with 65 additions and 10 deletions
+9 -3
View File
@@ -157,7 +157,7 @@ Visit the [Community Scripts page](https://community-scripts.github.io/ProxmoxVE
**Steps:**
1. **Create a Directory:** Make a directory on your Docker host where Pulse will store configuration:
1. **Create a Directory:** Make a directory for your Docker configuration files:
```bash
mkdir pulse-config
cd pulse-config
@@ -175,8 +175,14 @@ Visit the [Community Scripts page](https://community-scripts.github.io/ProxmoxVE
# Change the left side (e.g., "8081:7655") if 7655 is busy on your host
- "7655:7655"
volumes:
# Mount local directory for persistent configuration
- ./pulse-data:/opt/pulse-proxmox
# Persistent volume for configuration data
# Configuration persists across container updates
- pulse_config:/usr/src/app/config
# Define persistent volumes
volumes:
pulse_config:
driver: local
```
3. **Run:** Start the container:
```bash
+13 -3
View File
@@ -11,13 +11,23 @@ services:
# Map container port 7655 to host port 7655
# You can change the host port (left side) if 7655 is already in use on your host
- "7655:7655"
env_file:
# Load environment variables from a .env file in the same directory as this compose file
- .env # Standard location
# env_file:
# NOTE: .env file is now managed by the web UI and stored in persistent volume
# No need to load from host .env file
# - .env
volumes:
# Persist configuration data to avoid losing settings on container recreation
# Mount a persistent volume for configuration files
- pulse_config:/usr/src/app/config
# Optional: Define networks if needed, otherwise uses default bridge network
# networks:
# - pulse_network
# Define persistent volumes for configuration and data
volumes:
pulse_config:
driver: local
# Optional: Define a network
# networks:
# pulse_network:
+11 -1
View File
@@ -1,11 +1,21 @@
const fs = require('fs').promises;
const fsSync = require('fs');
const path = require('path');
const { loadConfiguration } = require('./configLoader');
const { initializeApiClients } = require('./apiClients');
class ConfigApi {
constructor() {
this.envPath = path.join(__dirname, '../.env');
// Use persistent config directory if it exists (for Docker), otherwise use project root
const configDir = path.join(__dirname, '../config');
const projectRootEnv = path.join(__dirname, '../.env');
// Check if we're in a Docker environment with persistent config volume
if (fsSync.existsSync(configDir)) {
this.envPath = path.join(configDir, '.env');
} else {
this.envPath = projectRootEnv;
}
}
/**
+12 -1
View File
@@ -98,7 +98,18 @@ function loadPbsConfig(index = null) {
function loadConfiguration() {
// Only load .env file if not in test environment
if (process.env.NODE_ENV !== 'test') {
require('dotenv').config();
const fs = require('fs');
const path = require('path');
const configDir = path.join(__dirname, '../config');
const configEnvPath = path.join(configDir, '.env');
const projectEnvPath = path.join(__dirname, '../.env');
if (fs.existsSync(configEnvPath)) {
require('dotenv').config({ path: configEnvPath });
} else {
require('dotenv').config({ path: projectEnvPath });
}
}
let isConfigPlaceholder = false; // Add this flag
+20 -2
View File
@@ -1,4 +1,17 @@
require('dotenv').config(); // Load environment variables from .env file
// Load environment variables from .env file
// Check for persistent config directory (Docker) or use project root
const fs = require('fs');
const path = require('path');
const configDir = path.join(__dirname, '../config');
const configEnvPath = path.join(configDir, '.env');
const projectEnvPath = path.join(__dirname, '../.env');
if (fs.existsSync(configEnvPath)) {
require('dotenv').config({ path: configEnvPath });
} else {
require('dotenv').config({ path: projectEnvPath });
}
// Import the state manager FIRST
const stateManager = require('./state');
@@ -998,7 +1011,12 @@ let lastReloadTime = 0;
global.lastReloadTime = 0; // Make it globally accessible
function setupEnvFileWatcher() {
const envPath = path.join(__dirname, '../.env');
// Use same logic as ConfigApi to find .env file
const configDir = path.join(__dirname, '../config');
const configEnvPath = path.join(configDir, '.env');
const projectEnvPath = path.join(__dirname, '../.env');
const envPath = fs.existsSync(configEnvPath) ? configEnvPath : projectEnvPath;
// Check if the file exists
if (!fs.existsSync(envPath)) {