Skip to the content.

Rustland

GitHub release License: MIT Rust Docker

A fast CLI tool for setting up local development environments using Docker, written in Rust.


Table of Contents


Features

Requirements


Installation

Quick Install (Linux x86_64)

curl -sSL https://raw.githubusercontent.com/civanmoreno/rustland/main/install.sh | bash

Manual Installation

  1. Download the latest release from GitHub Releases

  2. Extract the archive:
    tar -xzf rustland-*-linux-x86_64.tar.gz
    
  3. Move to your PATH:
    sudo mv rustland /usr/local/bin/
    
  4. Verify installation:
    rustland help
    

Build from Source

# Clone the repository
git clone https://github.com/civanmoreno/rustland.git
cd rustland

# Build the project
cargo build --release

# The binary will be at ./target/release/rustland
sudo cp ./target/release/rustland /usr/local/bin/

Quick Start

# Initialize with a recipe
rustland init --recipe laravel

# Or use interactive mode
rustland init

# Start the environment
rustland start

# Access your app at https://your-project.lvh.me:8443

Recipes

Rustland comes with pre-configured recipes for common development stacks:

Recipe Description Services
laravel Laravel PHP framework PHP, Nginx, MySQL, Redis
wordpress WordPress CMS PHP, Nginx, MariaDB
drupal Drupal CMS PHP, Nginx, PostgreSQL, Redis
lamp LAMP stack PHP, Apache, MySQL
lemp LEMP stack PHP, Nginx, MySQL
node Node.js runtime Node.js
fullstack Full stack development PHP, Nginx, Node.js, MySQL, Redis
custom Interactive configuration Choose your services

Using Recipes

# Initialize with Laravel recipe
rustland init --recipe laravel

# Initialize with WordPress recipe
rustland init --recipe wordpress

# Initialize with Node.js recipe
rustland init --recipe node

# Interactive mode (shows recipe selection)
rustland init

Configuration

Rustland uses a .rustland.yml file in your project root.

Example: Laravel with MySQL

name: my-laravel-app
services:
  appserver:
    type: php
    version: "8.2"
    variant: fpm
    webroot: ./public
    xdebug: true
  webserver:
    type: nginx
    version: latest
    webroot: ./public
  database:
    type: mysql
    version: "8.0"
    credentials:
      database: laravel
      user: laravel
      password: secret
  cache:
    type: redis
    version: "7"
proxy:
  webserver:
    - my-laravel-app.lvh.me

Example: Laravel with PostgreSQL

name: my-app
services:
  appserver:
    type: php
    version: "8.3"
    variant: fpm
    webroot: ./public
    xdebug: true
  webserver:
    type: nginx
    version: latest
    webroot: ./public
  database:
    type: postgresql
    version: "16"
    credentials:
      database: myapp
      user: myapp
      password: secret
  cache:
    type: redis
    version: "7"
proxy:
  webserver:
    - my-app.lvh.me

Example: WordPress with MariaDB

name: my-wordpress
services:
  appserver:
    type: php
    version: "8.2"
    variant: fpm
    webroot: ./
    xdebug: true
  webserver:
    type: nginx
    version: latest
    webroot: ./
  database:
    type: mariadb
    version: "10.11"
    credentials:
      database: wordpress
      user: wordpress
      password: wordpress
proxy:
  webserver:
    - my-wordpress.lvh.me

Example: Node.js (Next.js/Vite)

name: my-frontend
services:
  node:
    type: node
    version: "20"
    command: "npm install && npm run dev"
    ports:
      - "3000:3000"
    environment:
      HOST: "0.0.0.0"

Example: Full Stack (PHP + Node + MySQL + Redis)

name: fullstack-app
services:
  appserver:
    type: php
    version: "8.2"
    variant: fpm
    webroot: ./public
    xdebug: true
  webserver:
    type: nginx
    version: latest
    webroot: ./public
  database:
    type: mysql
    version: "8.0"
    credentials:
      database: app
      user: app
      password: secret
  cache:
    type: redis
    version: "7"
  frontend:
    type: node
    version: "20"
    command: "npm run dev"
    ports:
      - "5173:5173"
    environment:
      HOST: "0.0.0.0"
proxy:
  webserver:
    - fullstack-app.lvh.me

Example: Production Configuration with Workers

name: my-production-app
env: prod                    # Environment: dev, staging, prod
env_file:                    # Load environment files
  - .env
  - .env.local
services:
  appserver:
    type: php
    version: "8.2"
    variant: fpm
    webroot: ./public
    restart: always          # Restart policy for production
    resources:               # Resource limits
      cpus: "1"
      memory: "512m"
    healthcheck:             # Health check
      test: "php-fpm-healthcheck || exit 1"
      interval: "30s"
      timeout: "10s"
      retries: 3
    depends_on:              # Start order
      - database
      - cache
  worker:
    type: php
    version: "8.2"
    variant: cli             # CLI variant for workers
    command: "php artisan queue:work --sleep=3 --tries=3"
    restart: always
    resources:
      cpus: "0.5"
      memory: "256m"
    depends_on:
      - database
      - cache
  webserver:
    type: nginx
    version: latest
    webroot: ./public
    restart: always
  database:
    type: mysql
    version: "8.0"
    restart: always
    resources:
      cpus: "2"
      memory: "1g"
    credentials:
      database: app
      user: app
      password: ${DB_PASSWORD}
  cache:
    type: redis
    version: "7"
    restart: always
proxy:
  webserver:
    - my-production-app.lvh.me
tooling:
  composer:
    service: appserver
    cmd: composer
  artisan:
    service: appserver
    cmd: php artisan

Production Deployment

Export to Docker Compose

Export your Rustland configuration to a docker-compose.yml file for production deployment:

# Export for production
rustland export --env prod

# Export with custom output file
rustland export --output docker-compose.prod.yml --env prod

Environment-based Configuration

Rustland supports different environments that affect default behaviors:

Environment Restart Policy Description
dev no Development (default)
staging on-failure Staging/testing
prod always Production

Environment Files

Load environment variables from .env files:

name: my-app
env_file:
  - .env              # Base environment
  - .env.local        # Local overrides (git-ignored)
  - .env.${ENV}       # Environment-specific

Restart Policies

Policy Description
no Never restart (default for dev)
always Always restart (default for prod)
on-failure Restart only on failure
unless-stopped Restart unless explicitly stopped

Resource Limits

Limit CPU and memory usage per service:

services:
  appserver:
    type: php
    version: "8.2"
    resources:
      cpus: "1.5"           # 1.5 CPU cores
      memory: "512m"        # 512 MB memory
      memory_reservation: "256m"  # Soft limit

Health Checks

Configure health checks to monitor service status:

services:
  database:
    type: mysql
    version: "8.0"
    healthcheck:
      test: "mysqladmin ping -h localhost"
      interval: "30s"
      timeout: "10s"
      retries: 3
      start_period: "60s"

Workers and Background Processes

Run background workers using the CLI variant:

services:
  # Queue worker
  worker:
    type: php
    version: "8.2"
    variant: cli
    command: "php artisan queue:work"
    restart: always

  # Scheduler
  scheduler:
    type: php
    version: "8.2"
    variant: cli
    command: "php artisan schedule:work"
    restart: always

Services

Service Type Versions Docker Image
PHP php 8.3, 8.2, 8.1, 8.0, 7.4 serversideup/php:{version}-{variant}
Nginx nginx latest nginx (official)
MySQL mysql 8.4, 8.0, 5.7 mysql (official)
MariaDB mariadb 10.x, 11.x mariadb (official)
PostgreSQL postgresql 15, 14, 13 postgres (official)
Redis redis 7, 6 redis (official, alpine)
Node.js node 20, 18, 16 node (official, alpine)

PHP Image

We use serversideup/php for PHP with configurable variants.

Available variants:

Variant Image Use case
fpm (default) serversideup/php:8.2-fpm Web apps with Nginx/Apache
fpm-alpine serversideup/php:8.2-fpm-alpine Lightweight web apps
cli serversideup/php:8.2-cli CLI scripts, workers, queues
cli-alpine serversideup/php:8.2-cli-alpine Lightweight CLI apps

Configuration example:

services:
  appserver:
    type: php
    version: "8.2"
    variant: fpm          # optional, defaults to "fpm"
  worker:
    type: php
    version: "8.2"
    variant: cli          # for queue workers

Why serversideup/php?

Nginx

We use the official nginx image.

Image format: nginx:{version}

Examples:

Configuration example:

services:
  webserver:
    type: nginx
    version: latest       # or "1.25", "1.24", "alpine"
    webroot: ./public

Features:

MySQL

We use the official mysql image.

Image format: mysql:{version}

Available versions: 8.4, 8.0, 5.7

Examples:

Configuration example:

services:
  database:
    type: mysql
    version: "8.0"
    credentials:
      database: myapp
      user: myapp
      password: secret

Environment variables set automatically:

MariaDB

We use the official mariadb image.

Image format: mariadb:{version}

Available versions: 11.x, 10.x (10.11, 10.6, etc.)

Examples:

Configuration example:

services:
  database:
    type: mariadb
    version: "10.11"
    credentials:
      database: myapp
      user: myapp
      password: secret

Environment variables set automatically:

PostgreSQL

We use the official postgres image.

Image format: postgres:{version}

Available versions: 16, 15, 14, 13

Examples:

Configuration example:

services:
  database:
    type: postgresql
    version: "15"
    credentials:
      database: myapp
      user: myapp
      password: secret

Environment variables set automatically:

Redis

We use the official redis Alpine image for a lightweight footprint.

Image format: redis:{version}-alpine

Available versions: 7, 6

Examples:

Configuration example:

services:
  cache:
    type: redis
    version: "7"

Features:

Node.js

We use the official node Alpine image.

Image format: node:{version}-alpine

Available versions: 22, 20, 18, 16

Examples:

Configuration example:

services:
  node:
    type: node
    version: "20"
    command: "npm run dev"
    ports:
      - "3000:3000"

Features:

Example for Vite/Next.js:

services:
  frontend:
    type: node
    version: "20"
    command: "npm install && npm run dev"
    ports:
      - "5173:5173"    # Vite default port
    environment:
      HOST: "0.0.0.0"  # Required for container access

Commands

Command Description
rustland init Initialize a new project with interactive prompts
rustland init --recipe laravel Initialize with a specific recipe
rustland start Start all services
rustland stop Stop all services
rustland destroy Remove all containers, networks and volumes
rustland status Show status of all services
rustland logs [service] View logs for a service
rustland shell [service] Open a shell in a container
rustland rebuild Rebuild containers
rustland config Show current configuration
rustland info Show project information and configuration summary
rustland export Export to docker-compose.yml for production
rustland db import Import SQL file to database
rustland db export Export database to SQL file

Tooling

Rustland allows you to run tools inside your containers without manually using docker exec. Tools are configured in the tooling section of your .rustland.yml.

Using Tools

# Run composer
rustland composer install
rustland composer require laravel/sanctum

# Run artisan (Laravel)
rustland artisan migrate
rustland artisan make:controller UserController

# Run npm
rustland npm install
rustland npm run dev

# Run php
rustland php -v
rustland php artisan tinker

Default Tools by Recipe

Recipe Available Tools
Laravel composer, artisan, php, npm
WordPress wp, composer, php
Drupal drush, composer, php
LAMP/LEMP composer, php
Node npm, node, yarn, npx
Full Stack composer, artisan, php, npm, node, yarn

Custom Tooling Configuration

You can define custom tools in your .rustland.yml:

name: my-project
services:
  appserver:
    type: php
    version: "8.2"
  # ... other services

tooling:
  composer:
    service: appserver
    cmd: composer
  artisan:
    service: appserver
    cmd: php artisan
  php:
    service: appserver
    cmd: php
  npm:
    service: appserver
    cmd: npm
  test:
    service: appserver
    cmd: php artisan test
  lint:
    service: appserver
    cmd: ./vendor/bin/pint

Tool Options

Option Description
service Container to run the command in
cmd Base command to execute
user User to run command as (optional)

Examples

# Install dependencies
rustland composer install
rustland npm install

# Run database migrations
rustland artisan migrate

# Run tests
rustland artisan test

# Create a new controller
rustland artisan make:controller PostController

# Run code formatter
rustland lint

# Interactive PHP shell
rustland php artisan tinker

How it Works

  1. Init - rustland init creates a .rustland.yml configuration file
  2. Start - rustland start reads the config and:
    • Creates a Docker network for the project
    • Starts Traefik proxy (if not running) on ports 8080/8443
    • Creates and starts containers for each service
    • Configures routing through Traefik
  3. Access - Your app is available at https://{project-name}.lvh.me:8443

Networking

HTTPS


Project Structure

rustland/
├── src/
│   ├── main.rs              # Entry point
│   ├── cli/
│   │   ├── mod.rs           # CLI definition
│   │   └── commands/        # Command implementations
│   ├── config/
│   │   ├── schema.rs        # Configuration structs
│   │   └── validation.rs    # Config validation
│   ├── docker/
│   │   ├── client.rs        # Docker API client
│   │   ├── compose.rs       # Compose generation
│   │   ├── network.rs       # Network management
│   │   └── proxy.rs         # Traefik proxy
│   ├── services/            # Service definitions
│   ├── templates/           # Config templates
│   └── utils/               # Utilities
├── Cargo.toml
└── README.md

Comparison with Lando

Rustland is inspired by Lando but with some differences:

Feature Rustland Lando
Language Rust Node.js
Startup time Fast Moderate
Configuration .rustland.yml .lando.yml
HTTPS Traefik + self-signed Traefik + CA
Docker Compose Direct Docker API docker-compose

License

MIT


Contributing

Contributions are welcome! Please feel free to submit a Pull Request on GitHub.


Back to Top