- Add complete dark mode system with theme context and toggle - Implement dark mode toggle component in navigation menu - Add client-side routing with SSR-safe signal handling - Fix language selector styling for better dark mode compatibility - Add documentation system with mdBook integration - Improve navigation menu with proper external/internal link handling - Add comprehensive project documentation and configuration - Enhance theme system with localStorage persistence - Fix arena panic issues during server-side rendering - Add proper TypeScript configuration and build optimizations 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
8.3 KiB
ROOT_PATH Configuration Guide
This document explains how to use the ROOT_PATH configuration feature to manage absolute and relative paths in your Rust application.
Overview
The ROOT_PATH configuration allows you to:
- Convert all relative paths in configuration files to absolute paths
- Set a base directory for your application
- Deploy your application anywhere without hardcoding paths
- Maintain consistent path resolution across different environments
Configuration
Setting ROOT_PATH
There are several ways to set the ROOT_PATH:
1. Environment Variable (Recommended)
export ROOT_PATH=/path/to/your/application
2. Configuration File
# config.toml
root_path = "/path/to/your/application"
3. Default Behavior
If not set, ROOT_PATH defaults to the current working directory.
Environment Variable Priority
The ROOT_PATH can be overridden using the ROOT_PATH environment variable:
# Override config file setting
ROOT_PATH=/custom/path ./target/release/server
Path Resolution
How It Works
-
Absolute Paths: Left unchanged
- Input:
/absolute/path/to/file - Output:
/absolute/path/to/file
- Input:
-
Relative Paths: Resolved against
ROOT_PATH- ROOT_PATH:
/app - Input:
public/assets - Output:
/app/public/assets
- ROOT_PATH:
-
Current Directory References: Resolved properly
- ROOT_PATH:
/app - Input:
./config - Output:
/app/config
- ROOT_PATH:
-
Parent Directory References: Resolved properly
- ROOT_PATH:
/app/server - Input:
../shared - Output:
/app/shared
- ROOT_PATH:
Affected Configuration Sections
The following configuration sections have their paths resolved:
Static Files
[static]
assets_dir = "public" # -> /app/public
site_root = "target/site" # -> /app/target/site
site_pkg_dir = "pkg" # -> /app/pkg
Server Directories
[server_dirs]
public_dir = "public" # -> /app/public
uploads_dir = "uploads" # -> /app/uploads
logs_dir = "logs" # -> /app/logs
temp_dir = "tmp" # -> /app/tmp
cache_dir = "cache" # -> /app/cache
config_dir = "config" # -> /app/config
data_dir = "data" # -> /app/data
backup_dir = "backups" # -> /app/backups
TLS Configuration
[server.tls]
cert_path = "certs/server.crt" # -> /app/certs/server.crt
key_path = "certs/server.key" # -> /app/certs/server.key
Logging
[logging]
file_path = "logs/app.log" # -> /app/logs/app.log
Content Directory (if enabled)
[content]
content_dir = "content" # -> /app/content
Usage Examples
Development Environment
# Set ROOT_PATH to your project directory
export ROOT_PATH=/home/user/my-rust-app
cd /home/user/my-rust-app
cargo run
Production Deployment
# Docker example
FROM rust:latest
WORKDIR /app
COPY . .
ENV ROOT_PATH=/app
ENV ENVIRONMENT=production
RUN cargo build --release
EXPOSE 3030
CMD ["./target/release/server"]
Systemd Service
[Unit]
Description=My Rust Application
After=network.target
[Service]
Type=simple
User=myapp
WorkingDirectory=/opt/myapp
Environment=ROOT_PATH=/opt/myapp
Environment=ENVIRONMENT=production
ExecStart=/opt/myapp/target/release/server
Restart=always
[Install]
WantedBy=multi-user.target
Directory Structure
Recommended Layout
ROOT_PATH/
├── config.toml
├── config.dev.toml
├── config.prod.toml
├── target/
│ └── release/
│ └── server
├── public/ # Static assets
├── content/ # Content files
├── uploads/ # User uploads
├── logs/ # Application logs
├── cache/ # Temporary cache
├── data/ # Application data
├── backups/ # Backup files
└── certs/ # TLS certificates
├── server.crt
└── server.key
API Reference
Config Methods
get_absolute_path(relative_path: &str) -> Result<String, ConfigError>
Converts a relative path to an absolute path using the configured ROOT_PATH.
use server::config::Config;
let config = Config::load()?;
let absolute_path = config.get_absolute_path("uploads/images")?;
println!("Absolute path: {}", absolute_path);
// Output: /app/uploads/images
Environment Variables
| Variable | Description | Default |
|---|---|---|
ROOT_PATH |
Base directory for path resolution | Current directory |
CONFIG_FILE |
Explicit path to config file | Auto-discovered |
ENVIRONMENT |
Runtime environment | development |
Migration Guide
Converting Hardcoded Paths
Before (Hardcoded)
// Don't do this
let config_path = "../../../config.toml";
let content_path = "../../content/menu.toml";
After (ROOT_PATH)
// Do this instead
let config = Config::load()?;
let uploads_path = config.get_absolute_path("uploads")?;
let content_path = config.get_absolute_path("content/menu.toml")?;
Content Loading
Before
// Hardcoded relative path
let content = include_str!("../../content/menu.toml");
After
// Dynamic path resolution
use shared::get_content_path;
let menu_path = get_content_path("menu.toml")?;
let content = std::fs::read_to_string(menu_path)?;
Best Practices
1. Use Environment Variables in Production
# Production
export ROOT_PATH=/opt/myapp
export ENVIRONMENT=production
export DATABASE_URL=postgresql://...
2. Keep Config Files Portable
# Use relative paths in config files
[server_dirs]
public_dir = "public" # Good
# public_dir = "/var/www" # Avoid hardcoded absolute paths
3. Document Your Directory Structure
# config.toml
# Directory structure:
# ROOT_PATH/
# ├── public/ -> static assets
# ├── uploads/ -> user uploads
# ├── logs/ -> application logs
# └── data/ -> application data
[server_dirs]
public_dir = "public"
uploads_dir = "uploads"
logs_dir = "logs"
data_dir = "data"
4. Use Consistent Naming
# Consistent directory naming
[server_dirs]
public_dir = "public" # Not "static" or "assets"
uploads_dir = "uploads" # Not "files" or "media"
logs_dir = "logs" # Not "log" or "logging"
Troubleshooting
Common Issues
1. Path Not Found
Error: Root path '/invalid/path' does not exist
Solution: Ensure the ROOT_PATH directory exists and is accessible.
2. Permission Denied
Error: Directory creation error: Permission denied
Solution: Check file permissions and ensure the application has write access.
3. Config File Not Found
Error: Configuration file 'config.toml' not found
Solution: Ensure the config file exists in the ROOT_PATH directory.
Debug Commands
# Check current configuration
cargo run --bin config_tool -- show
# Validate configuration
cargo run --bin config_tool -- validate
# Generate new config
cargo run --bin config_tool -- generate dev
Testing
Unit Tests
#[test]
fn test_path_resolution() {
use std::env;
// Set test ROOT_PATH
env::set_var("ROOT_PATH", "/tmp/test");
let config = Config::load().unwrap();
let absolute_path = config.get_absolute_path("uploads").unwrap();
assert!(absolute_path.starts_with("/tmp/test"));
assert!(absolute_path.ends_with("uploads"));
}
Integration Tests
# Test with different ROOT_PATH values
ROOT_PATH=/tmp/test1 cargo test
ROOT_PATH=/var/tmp/test2 cargo test
Security Considerations
- Path Traversal: The system prevents
../attacks by resolving paths properly - Permissions: Ensure the
ROOT_PATHdirectory has appropriate permissions - Validation: All paths are validated before use
- Sandboxing: Consider using chroot or containers for additional security
Performance
- Path resolution is performed once at startup
- Resolved paths are cached in the configuration
- No runtime overhead for path lookups
- Canonical path resolution may involve filesystem access