Famlab CLI Architecture¶
Overview¶
The Famlab CLI is designed as a modular, extensible command-line interface for managing a Famlab deployment. It provides direct management of Proxmox VE containers.
Design Principles¶
- Modular Command Structure: Each command is a separate script for easy extension
- Direct Container Management: No complex orchestration dependencies
- Zero Configuration Overhead: Sensible defaults with optional customization
- Extensible Architecture: New commands can be added without modifying core router
- Human-oriented CLI: The interface is meant to be helpful and guided
- Working Directory Aware: The working directory contains the Famlab node inventory used by all commands
- Expected Behavior: The commands are not surprising and follow standard practices
-s
,--silent
will silence all stdout messages (keeping stderr for errors)-f
,--force
will override and bypass any warning raised during a WRITE operation-n
,--dry-run
will display what would have happened during a WRITE operation-v
,--verbose
will increase the verbosity to DEBUG level (the default is INFO)- ambiguous state resolution should ask for confirmation and default to no destruction (
-f
would force a "yes", and-n
would force a "no")
Typical Use¶
(Once the CLI is installed, see Installation Process first.)
% mkdir my-famlab
% cd my-famlab
% famlab init famlab-1 famlab-2 famlab-3]
[…]
% famlab bootstrap proxmox-ve.local
[…]
Famlab nodes 'famlab-1', 'famlab-2', 'famlab-3' bootstrapped successfully
% famlab deploy
[…]
Famlab nodes 'famlab-1', 'famlab-2', 'famlab-3' deployed successfully
% famlab ping
[…]
Famlab nodes 'famlab-1', 'famlab-2', 'famlab-3' pinged successfully
% famlab test
[…]
Famlab nodes 'famlab-1', 'famlab-2', 'famlab-3] tested successfully
Directory Structure¶
famlab.net/
├── bin/famlab # Main CLI router script
├── scripts/install.sh # Installation script for the CLI
└── share/famlab/ # Shared data
├── commands/ # Command implementations
│ ├── famlab-init # Initialize configuration
│ ├── famlab-bootstrap # Create containers
│ ├── famlab-deploy # Configure services
│ ├── famlab-ping # Test connectivity
│ ├── famlab-test # Full service testing
│ └── famlab-user # User management
└── lib/ # Shared library functions
└── famlab-core.sh # Core functionality
Command Architecture¶
Main Router (bin/famlab
)¶
- POSIX-compatible shell script
- Validates subcommand exists in
commands/
directory - Routes execution to appropriate command script
- Provides top-level help and listing of available subcommands
Individual Commands (share/famlab/commands/famlab-*
)¶
- Self-contained POSIX shell scripts
- Source shared library (
../lib/famlab-core.sh
) - Implement specific functionality for Famlab management
- Handle their own argument parsing and validation
Shared Library (share/famlab/lib/famlab-core.sh
)¶
- Common functions for Famlab operations
- Logging, error handling, container operations
- IP resolution, connectivity testing
- SMB configuration utilities
Command Specifications¶
famlab init HOSTNAME...
¶
Purpose: Initialize local configuration for Famlab deployment
Functionality:
- Create local inventory file with specified hostnames in the current directory
- Validate hostname format (strip
.local
suffixes with warning) - Accept plain hostnames and FQDNs, reject IP addresses
Example:
% famlab init famlab-1 famlab-2.local famlab-3.example.com
WARNING: Hostname 'famlab-2.local' is suffixed with 'local', stripping mDNS suffix ('famlab-2')
Famlab deployment initialized successfully, hosts inventory saved to 'inventory.ini'
% cat inventory.ini
; Famlab Inventory
; Generated by: famlab init famlab-1 famlab-2.local famlab-3.example.com
famlab-1
famlab-2
famlab-3.example.com
famlab bootstrap PVE [HOSTNAME...]
¶
Purpose: Create Proxmox VE containers for Famlab nodes
Functionality:
- SSH to Proxmox VE and create containers
- Default configuration: 1 CPU, 512MiB RAM, 32GiB disk, DHCP IPv4
- Install SSHd and allow current user to remote login as root
- Warn against invalid configuration (ask for confirmation)
- … both IPv4 and IPv6 disabled
- … less than 8GiB disk
- … less than 512MiB RAM
- Optional overrides via command arguments
- Bootstrap all hosts from inventory, unless hostnames are given as positional arguments
Arguments:
--cpu <cores>
- Override CPU count--memory <mib>
- Override memory allocation--disk <gib>
- Override disk size--ipv4 dhcp|disabled
- IPv4 configuration--ipv6 dhcp|disabled
- IPv6 configuration--storage <pool>
- Proxmox storage poolPVE
- Proxmox VE hostname to execute remote commands from (SSH)[HOSTNAME...]
- Bootstrap specific hosts only
Example:
% famlab bootstrap proxmox-ve.local
Remote logging to 'root@proxmox-ve.local' successful
famlab-1: container created
famlab-1: container booted
famlab-1: resolved to 192.168.0.101
famlab-2: container created
famlab-2: container booted
famlab-2: resolved to 192.168.0.102
famlab-3.example.com: container created
famlab-3.example.com: container booted
famlab-3.example.com: resolved to 192.168.0.103
Famlab nodes 'famlab-1', 'famlab-2', 'famlab-3.example.com' bootstrapped successfully
famlab deploy [HOSTNAME...]
¶
Purpose: Configure existing containers as home backup servers
Functionality:
- Install and configure: Samba, Avahi, unattended-upgrades
- Configure mDNS resolution
- Set up basic SMB shares (homes, anonymous
backup
share) without users - Configure SMB to automatically create corresponding host users when SMB users are created
- Handle re-runs gracefully (e.g. update existing configuration in-place rather than appending)
- Deploy all hosts from inventory, unless hostnames are given as positional arguments
Arguments:
[HOSTNAME...]
- Deploy specific hosts only
Example:
% famlab deploy
famlab-1: packages installed
famlab-1: Samba configured
famlab-1: unattended-upgrades configured
famlab-2: packages installed
famlab-2: Samba configured
famlab-2: unattended-upgrades configured
famlab-3.example.com: packages installed
famlab-3.example.com: Samba configured
famlab-3.example.com: unattended-upgrades configured
Famlab nodes 'famlab-1', 'famlab-2', 'famlab-3.example.com' deployed successfully
famlab ping [HOSTNAME...]
¶
Purpose: Test network connectivity of containers
Functionality:
- Test network connectivity and hostname resolution via
ping
- Display resolved IP addresses
- Ping all hosts from inventory, unless hostnames are given as positional arguments
Arguments:
[HOSTNAME...]
- Ping specific hosts only
Example:
% famlab ping famlab-1 famlab-3.example.com
famlab-1: network connectivity tested
famlab-1: resolved to 192.168.0.101
famlab-3.example.com: network connectivity tested
famlab-3.example.com: resolved to 192.168.0.103
Famlab nodes 'famlab-1', 'famlab-2', 'famlab-3.example.com' pinged successfully
famlab test [HOSTNAME...]
¶
Purpose: Test services of Famlab nodes
Functionality:
- Test remote login as root with SSH
- Test SMB service availability and configuration
- Test mDNS resolution
- Check basic SMB functionality (without user-specific tests)
- Test all hosts from inventory, unless hostnames are given as positional arguments
Arguments:
[HOSTNAME...]
- Test specific hosts only
Example:
% famlab test famlab-1
famlab-1: remote logging as root successful
famlab-1: SMB is available and configured
famlab-1: anonymous SMB share is readable and writable
famlab-1: personal SMB share is readable and writable
famlab-1: mDNS resolved to 192.168.0.101
Famlab node 'famlab-1' tested successfully
famlab user HOSTNAME OPERATION
¶
Purpose: Manage SMB/host user accounts on a Famlab node
Functionality:
- Manage SMB user accounts
- Set default password to username
Arguments:
HOSTNAME
- Target Famlab nodeOPERATION
- Where operation is one of:list
(list existing users),add USERNAME
(create a new SMB user),remove USERNAME
(remove an SMB user)
Example:
% famlab user famlab-1 list
Famlab node 'famlab-1' has no SMB users
% famlab user famlab-1 add borjan
New user 'borjan' created on Famlab node 'famlab-1'
% famlab user famlab-1 list
Famlab node 'famlab-1' has 1 SMB user: 'borjan'
Installation Process¶
scripts/install.sh
¶
- Copy
bin/famlab
to$HOME/.local/bin/famlab
with executable permissions - Recursively copy
share/famlab/
to${XDG_DATA_HOME:-$HOME/.local/share}/famlab/
- Ensure
$HOME/.local/bin
is in PATH (warn if not) - Set executable permissions on all command scripts
Paths¶
- Main CLI:
$HOME/.local/bin/famlab
- Commands:
${XDG_DATA_HOME:-$HOME/.local/share}/famlab/commands/
- Library:
${XDG_DATA_HOME:-$HOME/.local/share}/famlab/lib/
Configuration File Format¶
Inventory File (inventory.ini
)¶
Simple format for storing Famlab node information:
; Famlab Inventory
; Generated by: famlab init
famlab-1
famlab-2
famlab-3.example.com
Format Rules:
- One hostname per line
- Comments start with
;
- Empty lines ignored
- No
.local
suffixes stored - FQDNs stored as-is
Implementation Notes¶
Exit Codes¶
0
- Success1
- General error2
- Invalid arguments3
- Missing dependencies
Extension Points¶
Adding New Commands¶
- Create
share/famlab/commands/famlab-<newcommand>
- Source
../lib/famlab-core.sh
- Implement functionality
- Add help text and argument parsing
- Command automatically available via router
Library Extension¶
- Add new shared functions to
famlab-core.sh
- Maintain backward compatibility
- Follow established naming conventions