# 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) ```bash export ROOT_PATH=/path/to/your/application ``` #### 2. Configuration File ```toml # 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: ```bash # Override config file setting ROOT_PATH=/custom/path ./target/release/server ``` ## Path Resolution ### How It Works 1. **Absolute Paths**: Left unchanged - Input: `/absolute/path/to/file` - Output: `/absolute/path/to/file` 2. **Relative Paths**: Resolved against `ROOT_PATH` - ROOT_PATH: `/app` - Input: `public/assets` - Output: `/app/public/assets` 3. **Current Directory References**: Resolved properly - ROOT_PATH: `/app` - Input: `./config` - Output: `/app/config` 4. **Parent Directory References**: Resolved properly - ROOT_PATH: `/app/server` - Input: `../shared` - Output: `/app/shared` ### Affected Configuration Sections The following configuration sections have their paths resolved: #### Static Files ```toml [static] assets_dir = "public" # -> /app/public site_root = "target/site" # -> /app/target/site site_pkg_dir = "pkg" # -> /app/pkg ``` #### Server Directories ```toml [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 ```toml [server.tls] cert_path = "certs/server.crt" # -> /app/certs/server.crt key_path = "certs/server.key" # -> /app/certs/server.key ``` #### Logging ```toml [logging] file_path = "logs/app.log" # -> /app/logs/app.log ``` #### Content Directory (if enabled) ```toml [content] content_dir = "content" # -> /app/content ``` ## Usage Examples ### Development Environment ```bash # 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 ```bash # 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 ```ini [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` Converts a relative path to an absolute path using the configured `ROOT_PATH`. ```rust 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) ```rust // Don't do this let config_path = "../../../config.toml"; let content_path = "../../content/menu.toml"; ``` #### After (ROOT_PATH) ```rust // 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 ```rust // Hardcoded relative path let content = include_str!("../../content/menu.toml"); ``` #### After ```rust // 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 ```bash # Production export ROOT_PATH=/opt/myapp export ENVIRONMENT=production export DATABASE_URL=postgresql://... ``` ### 2. Keep Config Files Portable ```toml # 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 ```toml # 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 ```toml # 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 ```bash # 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 ```rust #[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 ```bash # Test with different ROOT_PATH values ROOT_PATH=/tmp/test1 cargo test ROOT_PATH=/var/tmp/test2 cargo test ``` ## Security Considerations 1. **Path Traversal**: The system prevents `../` attacks by resolving paths properly 2. **Permissions**: Ensure the `ROOT_PATH` directory has appropriate permissions 3. **Validation**: All paths are validated before use 4. **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 ## Related Documentation - [Configuration Guide](./CONFIGURATION.md) - [Deployment Guide](./DEPLOYMENT.md) - [Environment Variables](./ENVIRONMENT.md) - [Directory Structure](./DIRECTORY_STRUCTURE.md)