Skip to content

Commit 3408440

Browse files
author
Paul C
committed
Add configurable PHP session storage for multi-server deployments
- Add session_save_path config option for shared PHP sessions across servers - Interactive installer prompts for all configuration options - Support non-interactive install via environment variables (-y flag) - Document multi-server session sharing in README - Enables load balancing without sticky sessions
1 parent 89afea2 commit 3408440

5 files changed

Lines changed: 196 additions & 29 deletions

File tree

README.md

Lines changed: 62 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@ port = 3000
101101

102102
[php]
103103
fpm_address = "127.0.0.1:9993"
104+
session_save_path = "/mnt/shared/wolfserve/sessions"
104105

105106
[apache]
106107
# Load existing Apache vhost configs
@@ -109,6 +110,66 @@ fpm_address = "127.0.0.1:9993"
109110
config_dir = "/etc/apache2"
110111
```
111112

113+
## 🌐 Multi-Server PHP Sessions
114+
115+
WolfServe supports shared PHP sessions across multiple servers, enabling seamless load balancing without sticky sessions.
116+
117+
### Configuration
118+
119+
Set `session_save_path` in `wolfserve.toml` to a shared network location:
120+
121+
```toml
122+
[php]
123+
fpm_address = "127.0.0.1:9993"
124+
session_save_path = "/mnt/shared/wolfserve/sessions"
125+
```
126+
127+
### How It Works
128+
129+
1. User logs in on **Server A** → session file created at `/mnt/shared/wolfserve/sessions/sess_abc123`
130+
2. Next request routed to **Server B** → reads the same session file from shared storage
131+
3. User stays logged in seamlessly across all servers
132+
133+
### Requirements
134+
135+
- All servers must mount the same shared storage (NFS, GlusterFS, Ceph, etc.)
136+
- Clocks should be synchronized (NTP) for consistent session expiry
137+
- The installer automatically sets correct permissions (`chmod 1733` with sticky bit)
138+
139+
### Interactive Installation
140+
141+
The service installer prompts for all configuration options:
142+
143+
```bash
144+
sudo ./install_service.sh
145+
146+
📝 Configuration Options (press Enter to accept defaults)
147+
148+
Server bind address [0.0.0.0]:
149+
Server port [3000]:
150+
PHP-FPM port [9993]:
151+
PHP session save path [/var/lib/php/sessions]: /mnt/shared/wolfserve/sessions
152+
Apache config directory [/etc/apache2]:
153+
```
154+
155+
### Non-Interactive Installation
156+
157+
Use environment variables for automated deployments:
158+
159+
```bash
160+
sudo WOLFSERVE_SESSION_PATH="/mnt/shared/wolfserve/sessions" \
161+
WOLFSERVE_PORT="3000" \
162+
./install_service.sh -y
163+
```
164+
165+
| Environment Variable | Description | Default |
166+
|---------------------|-------------|---------|
167+
| `WOLFSERVE_HOST` | Server bind address | `0.0.0.0` |
168+
| `WOLFSERVE_PORT` | Server port | `3000` |
169+
| `WOLFSERVE_FPM_PORT` | PHP-FPM port | `9993` |
170+
| `WOLFSERVE_SESSION_PATH` | PHP session save path | `/var/lib/php/sessions` |
171+
| `WOLFSERVE_APACHE_DIR` | Apache config directory | `/etc/apache2` |
172+
112173
## 📁 Project Structure
113174

114175
```
@@ -190,7 +251,7 @@ sudo systemctl status wolfserve
190251

191252
- **SELinux (Fedora/RHEL)**: The installer automatically configures SELinux permissions.
192253

193-
- **PHP Sessions**: The installer sets up `/var/lib/php/sessions` with correct permissions.
254+
- **PHP Sessions**: For single-server setups, sessions are stored in `/var/lib/php/sessions`. For multi-server deployments, configure `session_save_path` to point to shared storage (see [Multi-Server PHP Sessions](#-multi-server-php-sessions)).
194255

195256
## 🏗️ Building from Source
196257

install_service.sh

Lines changed: 111 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -2,30 +2,101 @@
22

33
# WolfServe Service Installer
44
# Installs WolfServe as a systemd service on Linux
5+
#
6+
# Usage: ./install_service.sh [-y|--yes]
7+
#
8+
# Environment variables (for non-interactive use):
9+
# WOLFSERVE_HOST - Server bind address (default: 0.0.0.0)
10+
# WOLFSERVE_PORT - Server port (default: 3000)
11+
# WOLFSERVE_FPM_PORT - PHP-FPM port (default: 9993)
12+
# WOLFSERVE_SESSION_PATH - PHP session save path (default: /var/lib/php/sessions)
13+
# WOLFSERVE_APACHE_DIR - Apache config directory (default: /etc/apache2 or /etc/httpd)
514

615
set -e
716

817
INSTALL_DIR="/opt/wolfserve"
918
SERVICE_NAME="wolfserve"
10-
PHP_FPM_PORT="9993"
19+
20+
# Parse arguments
21+
AUTO_YES=false
22+
for arg in "$@"; do
23+
case $arg in
24+
-y|--yes)
25+
AUTO_YES=true
26+
shift
27+
;;
28+
esac
29+
done
1130

1231
# Check if running as root
1332
if [ "$(id -u)" -ne 0 ]; then
1433
echo "❌ Please run as root (sudo ./install_service.sh)"
1534
exit 1
1635
fi
1736

18-
echo "🐺 Installing WolfServe as a service..."
37+
echo "🐺 WolfServe Service Installer"
38+
echo "=============================="
39+
echo ""
1940

20-
# Fix PHP sessions directory permissions
21-
echo "🔧 Fixing PHP sessions directory permissions..."
22-
for sessions_dir in /var/lib/php/sessions /var/lib/php/session; do
23-
if [ -d "$sessions_dir" ]; then
24-
chmod 777 "$sessions_dir"
25-
echo " ✅ Set permissions on $sessions_dir"
26-
break
41+
# ============================================
42+
# Configuration (interactive or from env vars)
43+
# ============================================
44+
45+
# Detect default Apache directory
46+
DEFAULT_APACHE_DIR="/etc/apache2"
47+
if [ -d "/etc/httpd" ] && [ ! -d "/etc/apache2" ]; then
48+
DEFAULT_APACHE_DIR="/etc/httpd"
49+
fi
50+
51+
# Set defaults from environment variables
52+
SERVER_HOST="${WOLFSERVE_HOST:-0.0.0.0}"
53+
SERVER_PORT="${WOLFSERVE_PORT:-3000}"
54+
PHP_FPM_PORT="${WOLFSERVE_FPM_PORT:-9993}"
55+
SESSION_SAVE_PATH="${WOLFSERVE_SESSION_PATH:-/var/lib/php/sessions}"
56+
APACHE_CONFIG_DIR="${WOLFSERVE_APACHE_DIR:-$DEFAULT_APACHE_DIR}"
57+
58+
if [ "$AUTO_YES" = false ]; then
59+
echo "📝 Configuration Options (press Enter to accept defaults)"
60+
echo ""
61+
62+
# Server settings
63+
read -p "Server bind address [$SERVER_HOST]: " INPUT
64+
SERVER_HOST="${INPUT:-$SERVER_HOST}"
65+
66+
read -p "Server port [$SERVER_PORT]: " INPUT
67+
SERVER_PORT="${INPUT:-$SERVER_PORT}"
68+
69+
# PHP settings
70+
read -p "PHP-FPM port [$PHP_FPM_PORT]: " INPUT
71+
PHP_FPM_PORT="${INPUT:-$PHP_FPM_PORT}"
72+
73+
read -p "PHP session save path [$SESSION_SAVE_PATH]: " INPUT
74+
SESSION_SAVE_PATH="${INPUT:-$SESSION_SAVE_PATH}"
75+
76+
# Apache settings
77+
read -p "Apache config directory [$APACHE_CONFIG_DIR]: " INPUT
78+
APACHE_CONFIG_DIR="${INPUT:-$APACHE_CONFIG_DIR}"
79+
fi
80+
81+
echo ""
82+
echo "📋 Configuration Summary:"
83+
echo " Server: $SERVER_HOST:$SERVER_PORT"
84+
echo " PHP-FPM: 127.0.0.1:$PHP_FPM_PORT"
85+
echo " Sessions: $SESSION_SAVE_PATH"
86+
echo " Apache dir: $APACHE_CONFIG_DIR"
87+
echo ""
88+
89+
if [ "$AUTO_YES" = false ]; then
90+
read -p "Proceed with installation? [Y/n]: " CONFIRM
91+
CONFIRM="${CONFIRM:-Y}"
92+
if [[ ! "$CONFIRM" =~ ^[Yy]$ ]]; then
93+
echo "Installation cancelled."
94+
exit 0
2795
fi
28-
done
96+
fi
97+
98+
echo ""
99+
echo "🐺 Installing WolfServe as a service..."
29100

30101
# 1. Determine Web User
31102
WEB_USER="www-data"
@@ -69,27 +140,28 @@ mkdir -p "$INSTALL_DIR"
69140
mkdir -p "$INSTALL_DIR/public"
70141

71142
# 4. Copy Files
72-
echo "Vk Copying files..."
143+
echo "📦 Copying files..."
73144
cp target/release/wolfserve "$INSTALL_DIR/"
74145
cp wolflib/target/release/libwolflib.so "$INSTALL_DIR/"
75146

76-
# Copy config if not exists, else keep existing
77-
if [ ! -f "$INSTALL_DIR/wolfserve.toml" ]; then
78-
if [ -f "wolfserve.toml" ]; then
79-
cp wolfserve.toml "$INSTALL_DIR/"
80-
elif [ -f "wolfserve.toml.example" ]; then
81-
cp wolfserve.toml.example "$INSTALL_DIR/wolfserve.toml"
82-
else
83-
# minimal config
84-
echo "[server]" > "$INSTALL_DIR/wolfserve.toml"
85-
echo "host = \"0.0.0.0\"" >> "$INSTALL_DIR/wolfserve.toml"
86-
echo "port = 3000" >> "$INSTALL_DIR/wolfserve.toml"
87-
echo "" >> "$INSTALL_DIR/wolfserve.toml"
88-
echo "[php]" >> "$INSTALL_DIR/wolfserve.toml"
89-
echo "fpm_address = \"127.0.0.1:$PHP_FPM_PORT\"" >> "$INSTALL_DIR/wolfserve.toml"
90-
echo "mode = \"fpm\"" >> "$INSTALL_DIR/wolfserve.toml"
91-
fi
92-
fi
147+
# Generate config with user-specified options
148+
echo "📝 Writing configuration to $INSTALL_DIR/wolfserve.toml..."
149+
cat > "$INSTALL_DIR/wolfserve.toml" <<EOF
150+
# WolfServe Configuration
151+
# Generated by install_service.sh on $(date)
152+
153+
[server]
154+
host = "$SERVER_HOST"
155+
port = $SERVER_PORT
156+
157+
[php]
158+
fpm_address = "127.0.0.1:$PHP_FPM_PORT"
159+
mode = "fpm"
160+
session_save_path = "$SESSION_SAVE_PATH"
161+
162+
[apache]
163+
config_dir = "$APACHE_CONFIG_DIR"
164+
EOF
93165

94166
# Copy public files
95167
# Only copy if source public exists
@@ -151,6 +223,16 @@ fi
151223

152224
if [ -n "$FPM_POOL_CONF" ]; then
153225
echo " Writing pool config to $FPM_POOL_CONF..."
226+
227+
# Create session directory if needed
228+
if [ ! -d "$SESSION_SAVE_PATH" ]; then
229+
echo " Creating session directory: $SESSION_SAVE_PATH"
230+
mkdir -p "$SESSION_SAVE_PATH"
231+
fi
232+
chown "$WEB_USER:$WEB_USER" "$SESSION_SAVE_PATH"
233+
chmod 1733 "$SESSION_SAVE_PATH"
234+
echo " ✅ Session save path: $SESSION_SAVE_PATH"
235+
154236
cat > "$FPM_POOL_CONF" <<EOF
155237
[wolfserve]
156238
user = $WEB_USER
@@ -163,6 +245,7 @@ pm.max_children = 5
163245
pm.start_servers = 2
164246
pm.min_spare_servers = 1
165247
pm.max_spare_servers = 3
248+
php_admin_value[session.save_path] = $SESSION_SAVE_PATH
166249
EOF
167250
echo " ✅ PHP-FPM pool configured."
168251
else

run_bin.sh

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,22 @@ trap cleanup INT TERM
3131

3232
echo "Starting WolfServe Environment..."
3333

34+
# Read session_save_path from wolfserve.toml config (defaults to /tmp if not found)
35+
SESSION_SAVE_PATH="/tmp"
36+
if [ -f "wolfserve.toml" ]; then
37+
CONFIGURED_PATH=$(grep -E "^session_save_path\s*=" wolfserve.toml | sed 's/.*=\s*"\(.*\)"/\1/' | tr -d ' ')
38+
if [ -n "$CONFIGURED_PATH" ]; then
39+
SESSION_SAVE_PATH="$CONFIGURED_PATH"
40+
# Create session directory if it doesn't exist
41+
if [ ! -d "$SESSION_SAVE_PATH" ]; then
42+
echo "Creating session directory: $SESSION_SAVE_PATH"
43+
mkdir -p "$SESSION_SAVE_PATH"
44+
chmod 1733 "$SESSION_SAVE_PATH"
45+
fi
46+
fi
47+
fi
48+
echo "PHP session save path: $SESSION_SAVE_PATH"
49+
3450
# 1. Start PHP-FPM
3551
# Check if port 9993 is already in use
3652
if command -v lsof >/dev/null 2>&1 && lsof -i :9993 >/dev/null 2>&1; then
@@ -57,6 +73,7 @@ php_admin_value[upload_max_filesize] = 256M
5773
php_admin_value[post_max_size] = 256M
5874
php_admin_value[upload_tmp_dir] = /tmp
5975
php_admin_value[max_file_uploads] = 20
76+
php_admin_value[session.save_path] = ${SESSION_SAVE_PATH:-/tmp}
6077
EOF
6178

6279
# Find the fpm binary

src/main.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,10 @@ struct PhpConfig {
145145
mode: String, // "fpm" or "cgi"
146146
#[serde(default = "default_cgi_path")]
147147
cgi_path: String,
148+
/// PHP session save path (e.g., "/mnt/shared/wolfserve/sessions")
149+
/// Used by shell scripts for PHP-FPM configuration
150+
#[allow(dead_code)]
151+
session_save_path: Option<String>,
148152
}
149153

150154
fn default_php_mode() -> String {

wolfserve.toml.example

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ port = 3000
66

77
[php]
88
fpm_address = "127.0.0.1:9993"
9+
# PHP session save path - set this for shared session storage
10+
# session_save_path = "/mnt/shared/wolfserve/sessions"
911

1012
[apache]
1113
# Set this to "/etc/apache2" (Debian/Ubuntu) or "/etc/httpd" (RHEL/CentOS)

0 commit comments

Comments
 (0)