| Crates.io | lmrc-postgres |
| lib.rs | lmrc-postgres |
| version | 0.3.16 |
| created_at | 2025-11-26 18:01:01.556385+00 |
| updated_at | 2025-12-11 13:28:56.114865+00 |
| description | PostgreSQL management library for the LMRC Stack - comprehensive library for managing PostgreSQL installations on remote servers via SSH |
| homepage | https://gitlab.com/lemarco/lmrc-stack/tree/main/libs/postgres-manager |
| repository | https://gitlab.com/lemarco/lmrc-stack |
| max_upload_size | |
| id | 1951945 |
| size | 282,941 |
Part of the LMRC Stack - Infrastructure-as-Code toolkit for building production-ready Rust applications
A comprehensive Rust library for managing PostgreSQL installations on remote servers via SSH.
ssh-managerAdd this to your Cargo.toml:
[dependencies]
lmrc-postgres = "0.1"
ssh-manager = "0.1"
tokio = { version = "1.0", features = ["full"] }
use lmrc_postgres::{PostgresConfig, PostgresManager};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Build PostgreSQL configuration
let config = PostgresConfig::builder()
.version("15")
.database_name("myapp")
.username("myuser")
.password("secure_password")
.listen_addresses("0.0.0.0/0")
.port(5432)
.max_connections(100)
.shared_buffers("256MB")
.build()?;
// Create manager and connect
let manager = PostgresManager::builder()
.config(config)
.server_ip("192.168.1.100")
.ssh_user("root")
.build()?;
// Install and configure PostgreSQL (idempotent)
manager.setup().await?;
// Test the connection
manager.test_connection().await?;
println!("PostgreSQL is ready!");
Ok(())
}
use lmrc_postgres::{PostgresConfig, PostgresManager};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let config = PostgresConfig::builder()
.version("15")
.database_name("production_db")
.username("app_user")
.password("strong_password")
.listen_addresses("10.0.0.0/8")
.port(5432)
.max_connections(200)
.shared_buffers("512MB")
.effective_cache_size("2GB")
.work_mem("16MB")
.maintenance_work_mem("128MB")
.checkpoint_completion_target(0.9)
.ssl(true)
.build()?;
let manager = PostgresManager::builder()
.config(config)
.server_ip("10.0.1.50")
.ssh_user("admin")
.private_ip("10.0.1.50")
.build()?;
manager.setup().await?;
Ok(())
}
use lmrc_postgres::{PostgresConfig, PostgresManager};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let config = PostgresConfig::builder()
.version("15")
.database_name("myapp")
.username("myuser")
.password("mypass")
.max_connections(200) // Changed from 100
.build()?;
let manager = PostgresManager::builder()
.config(config)
.server_ip("192.168.1.100")
.build()?;
// Detect configuration differences
let diff = manager.diff().await?;
if diff.has_changes() {
println!("Configuration changes detected:");
for change in diff.changes() {
println!(" {}", change);
}
// Apply changes
manager.apply_diff(&diff).await?;
println!("Configuration updated successfully");
} else {
println!("No configuration changes");
}
Ok(())
}
The library provides comprehensive validation and intelligent auto-tuning:
use lmrc_postgres::{
PostgresConfig, validate_comprehensive, auto_tune, WorkloadType
};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Example 1: Validate a configuration
let config = PostgresConfig::builder()
.version("15")
.database_name("myapp")
.username("myuser")
.password("secure_password")
.max_connections(1000)
.work_mem("100MB")
.build()?;
// Run comprehensive validation
let warnings = validate_comprehensive(&config)?;
for warning in warnings {
println!("Warning: {}", warning);
}
// Example 2: Auto-tune for your workload
let total_ram_mb = 16384; // 16GB RAM
let cpu_cores = 8;
// Get recommended settings for a web application
let tuned = auto_tune(total_ram_mb, cpu_cores, WorkloadType::Web);
// Build config with auto-tuned values
let config = PostgresConfig::builder()
.version("15")
.database_name("webapp")
.username("webuser")
.password("secure_password")
.max_connections(tuned.get("max_connections").unwrap().parse().unwrap())
.shared_buffers(tuned.get("shared_buffers").unwrap())
.effective_cache_size(tuned.get("effective_cache_size").unwrap())
.work_mem(tuned.get("work_mem").unwrap())
.build()?;
Ok(())
}
Validation Features:
Auto-Tuning Workload Types:
WorkloadType::Web - Web applications (moderate connections, OLTP + read-heavy)WorkloadType::Mixed - Mixed workload (OLTP + analytics)WorkloadType::DataWarehouse - Complex queries, fewer connectionsWorkloadType::Oltp - High-throughput OLTP (many connections, simple queries)use lmrc_postgres::{PostgresConfig, PostgresManager};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let config = PostgresConfig::builder()
.version("15")
.database_name("myapp")
.username("myuser")
.password("mypass")
.build()?;
let manager = PostgresManager::builder()
.config(config)
.server_ip("192.168.1.100")
.build()?;
// Check if already installed
if !manager.is_installed().await? {
println!("Installing PostgreSQL...");
manager.install().await?;
} else {
println!("PostgreSQL is already installed");
}
// Configure database
println!("Configuring database...");
manager.configure_database().await?;
// Configure server
println!("Configuring server...");
manager.configure_server().await?;
// Test connection
println!("Testing connection...");
manager.test_connection().await?;
println!("Setup complete!");
Ok(())
}
The library provides comprehensive safety features for configuration changes:
use lmrc_postgres::{PostgresConfig, PostgresManager};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let config = PostgresConfig::builder()
.version("15")
.database_name("myapp")
.username("myuser")
.password("mypass")
.max_connections(200) // Changing configuration
.build()?;
let manager = PostgresManager::builder()
.config(config)
.server_ip("192.168.1.100")
.build()?;
// 1. Dry-run: Preview changes without applying
let diff = manager.dry_run_configure().await?;
if diff.has_changes() {
println!("Would make {} changes:", diff.len());
println!("{}", diff);
}
// 2. Safe apply: Automatic backup and rollback on failure
manager.apply_diff_safe(&diff).await?;
// 3. Manual backup
let backup = manager.backup_config().await?;
println!("Backup created: {}", backup.timestamp);
// 4. Quick rollback to most recent backup (if needed)
// manager.rollback_config().await?;
// 5. List and manage backups
let backups = manager.list_backups().await?;
manager.cleanup_old_backups(5).await?; // Keep only 5 most recent
// 6. Read and parse pg_hba.conf
let pg_hba = manager.read_pg_hba().await?;
println!("Current authentication rules:\n{}", pg_hba);
Ok(())
}
Safety Features:
Comprehensive user and database lifecycle management with granular permission control:
use lmrc_postgres::{PostgresConfig, PostgresManager, Privilege};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let config = PostgresConfig::builder()
.version("15")
.database_name("postgres")
.username("postgres")
.password("postgres")
.build()?;
let manager = PostgresManager::builder()
.config(config)
.server_ip("192.168.1.100")
.build()?;
// 1. List existing users and databases
let users = manager.list_users().await?;
for user in users {
println!("User: {} (superuser: {})", user.name, user.is_superuser);
}
let databases = manager.list_databases().await?;
for db in databases {
println!("Database: {} (owner: {})", db.name, db.owner);
}
// 2. Create database with advanced options
manager.create_database_with_options(
"myapp_db",
Some("postgres"), // owner
Some("UTF8"), // encoding
Some("template0") // template
).await?;
// 3. Create users with different permission levels
manager.create_user_with_options(
"app_user",
"secure_password",
false, // not superuser
false, // cannot create databases
false, // cannot create roles
Some(50) // connection limit
).await?;
// 4. Grant granular privileges
manager.grant_privileges(
"myapp_db",
"app_user",
&[Privilege::Select, Privilege::Insert, Privilege::Update]
).await?;
// 5. Role-based access control
manager.create_role("readonly", false, false).await?;
manager.grant_privileges("myapp_db", "readonly", &[Privilege::Select]).await?;
manager.grant_role("readonly", "app_user").await?;
// 6. Update user password
manager.update_user_password("app_user", "new_password").await?;
// 7. Check existence
if manager.user_exists("app_user").await? {
println!("User exists!");
}
// 8. Cleanup (if needed)
// manager.revoke_role("readonly", "app_user").await?;
// manager.drop_user("app_user").await?;
// manager.drop_database("myapp_db").await?;
Ok(())
}
User & Database Operations:
list_users(), list_databases() - Query all users/databases with metadatacreate_database_with_options(), create_user_with_options() - Advanced creation with owner, encoding, capabilitiesdrop_database(), drop_user() - Safely remove users and databasesupdate_user_password() - Change user passwordsuser_exists(), database_exists() - Check if user/database existsgrant_privileges(), revoke_privileges() - 12+ privilege types (SELECT, INSERT, UPDATE, DELETE, TRUNCATE, REFERENCES, TRIGGER, CREATE, CONNECT, TEMPORARY, EXECUTE, USAGE, ALL)create_role(), grant_role(), revoke_role() - Create and assign roles for organized permissionsuse lmrc_postgres::{PostgresConfig, PostgresManager};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let config = PostgresConfig::builder()
.version("15")
.database_name("myapp")
.username("myuser")
.password("mypass")
.build()?;
let manager = PostgresManager::builder()
.config(config)
.server_ip("192.168.1.100")
.build()?;
// Uninstall but keep data
manager.uninstall(false).await?;
// Or uninstall and purge all data
manager.uninstall(true).await?;
Ok(())
}
let config = PostgresConfig::builder()
.version("15") // PostgreSQL version
.database_name("mydb") // Database name
.username("dbuser") // Database user
.password("securepass") // Database password
.listen_addresses("0.0.0.0/0") // CIDR notation
.port(5432) // Port number
.max_connections(100) // Max connections
.shared_buffers("256MB") // Shared buffers
.effective_cache_size("1GB") // Cache size
.work_mem("4MB") // Work memory
.maintenance_work_mem("64MB") // Maintenance memory
.wal_buffers("16MB") // WAL buffers
.checkpoint_completion_target(0.9) // Checkpoint target
.ssl(true) // Enable SSL
.add_config("key", "value") // Custom config
.build()?;
let manager = PostgresManager::builder()
.config(config) // PostgresConfig instance
.server_ip("192.168.1.100") // Server IP address
.ssh_user("root") // SSH username
.ssh_port(22) // SSH port
.private_ip("10.0.1.100") // Private IP (optional)
.build()?;
All operations are idempotent and can be safely run multiple times:
Installation & Setup:
is_installed() - Check if PostgreSQL is installedget_installed_version() - Get installed versioninstall() - Install PostgreSQLuninstall(purge) - Uninstall PostgreSQLconfigure_database() - Configure database and userconfigure_server() - Configure server settingsconfigure() - Configure both database and serversetup() - Complete installation and configurationtest_connection() - Test database connectionConfiguration Management:
diff() - Detect configuration changesapply_diff(diff) - Apply configuration changesdry_run_configure() - Preview changes without applyingapply_diff_safe(diff) - Apply with automatic rollback on failureBackup & Restore:
backup_config() - Create configuration backuplist_backups() - List all backupsrestore_backup(backup) - Restore specific backuprollback_config() - Quick rollback to most recentcleanup_old_backups(keep) - Manage backup historyread_pg_hba() - Read pg_hba.conf authentication rulesUser Management:
list_users() - List all PostgreSQL userscreate_user_with_options() - Create user with advanced optionsdrop_user(username) - Remove userupdate_user_password(username, password) - Change passworduser_exists(username) - Check if user existsDatabase Management:
list_databases() - List all databasescreate_database_with_options() - Create database with advanced optionsdrop_database(database) - Remove databasedatabase_exists(database) - Check if database existsPermission Management:
grant_privileges(db, user, privileges) - Grant granular privilegesrevoke_privileges(db, user, privileges) - Revoke privilegescreate_role(role, can_login, is_superuser) - Create rolegrant_role(role, user) - Grant role to userrevoke_role(role, user) - Revoke role from userversion - PostgreSQL version (e.g., "15", "14", "13")database_name - Database name to createusername - Database usernamepassword - Database passwordlisten_addresses - CIDR notation (default: "0.0.0.0/0")port - PostgreSQL port (default: 5432)max_connections - Maximum concurrent connectionsshared_buffers - Shared memory buffers (e.g., "256MB")effective_cache_size - Query optimizer cache sizework_mem - Memory for sorts and queriesmaintenance_work_mem - Memory for maintenance operationswal_buffers - Write-ahead log bufferscheckpoint_completion_target - Checkpoint spread (0.0-1.0)ssl - Enable SSL (default: false)extra_config - Additional custom parametersThe library provides comprehensive error types:
use lmrc_postgres::{Error, Result};
match manager.install().await {
Ok(_) => println!("Installation successful"),
Err(Error::AlreadyInstalled(version)) => {
println!("PostgreSQL {} already installed", version)
}
Err(Error::SshConnection(err)) => {
eprintln!("SSH connection failed: {}", err)
}
Err(Error::Installation(msg)) => {
eprintln!("Installation failed: {}", msg)
}
Err(err) => eprintln!("Error: {}", err),
}
All operations are designed to be idempotent:
This makes it safe to run operations multiple times without errors.
Run the test suite:
# Unit tests
cargo test
# Integration tests (requires SSH access to a test server)
cargo test --test integration
# All tests with logging
RUST_LOG=debug cargo test
See the examples/ directory for more usage examples:
basic_install.rs - Basic installationcustom_config.rs - Custom configurationdiff_detection.rs - Detect and apply changesuninstall.rs - Uninstall PostgreSQLRun an example:
cargo run --example basic_install
Currently supports:
Planned support:
Contributions are welcome! Please see CONTRIBUTING.md for guidelines.
Part of the LMRC Stack project. Licensed under either of:
at your option.
If you discover a security vulnerability, please email security@example.com instead of using the issue tracker.