homelab infrastructure services

Ubuntu Machine Setup Automation#

This project automates the setup of Ubuntu machines with NAS mounting, rootless Docker installation, and persistent environment variable management.

Features#

  • NAS Mount Configuration: Supports both CIFS/SMB and NFS mounting with automatic mount on boot
  • Rootless Docker: Installs Docker in rootless mode for enhanced security
  • Environment Variables: Manages environment variables from a .env file on the NAS
  • Boot Persistence: Ensures all configurations persist across reboots

Prerequisites#

  • Ubuntu 20.04 or later
  • User account with sudo privileges (see note below)
  • Network access to NAS
  • Internet connection for Docker installation

Sudo Access Required#

The installation user must be in the sudoers group. If you're not sure, check with:

groups | grep -q sudo && echo "You have sudo access" || echo "You need sudo access"

To add a user to the sudo group:

sudo usermod -aG sudo username

Then log out and log back in for the changes to take effect.

Quick Start#

Run this command on your Ubuntu machine:

curl -fsSL "https://tangled.sh/dynamicalsystem.com/machine/raw/main/install.sh?$(date +%s)" | bash

Or with custom installation directory:

curl -fsSL "https://tangled.sh/dynamicalsystem.com/machine/raw/main/install.sh?$(date +%s)" | INSTALL_DIR=/path/to/install bash

Option 2: Git Clone (Requires SSH access)#

If you have SSH access to the git repository:

curl -fsSL "https://tangled.sh/dynamicalsystem.com/machine/raw/main/install.sh?$(date +%s)" | USE_GIT=true bash

Or manually:

git clone git@tangled.sh:dynamicalsystem.com/machine ~/.local/opt/dynamicalsystem.machine
cd ~/.local/opt/dynamicalsystem.machine

Run the Setup#

Run the setup script:

cd ~/.local/opt/dynamicalsystem.machine
./setup.sh

Integration with tinsnip#

For centralized identity management and shared infrastructure services, install tinsnip first:

# 1. Install tinsnip (provides LDAP and infrastructure)
curl -fsSL "https://tangled.sh/dynamicalsystem.com/tinsnip/raw/main/install.sh?$(date +%s)" | bash
cd ~/.local/opt/dynamicalsystem.tinsnip && ./setup.sh

# 2. Install machine (will detect and integrate with tinsnip)  
curl -fsSL "https://tangled.sh/dynamicalsystem.com/machine/raw/main/install.sh?$(date +%s)" | bash
cd ~/.local/opt/dynamicalsystem.machine && ./setup.sh

Benefits of tinsnip integration:

  • Unified Identity: Same users and UIDs across all systems
  • NFS Permissions: Proper file ownership with rootless Docker
  • Service Dependencies: Machine services wait for infrastructure to be ready

See docs/tinsnip-integration.md for detailed integration guide.

Setup Process#

Follow the interactive prompts to:

  • Configure NAS connection (CIFS/SMB or NFS)
  • Set up environment variables
  • Install rootless Docker

After completion, log out and log back in for all changes to take effect

Individual Components#

You can run individual scripts if needed:

# Mount NAS only
./scripts/mount_nas.sh

# Install Docker only
./scripts/install_docker.sh

# Configure environment variables
./scripts/manage_env.sh

# Set up boot services
./scripts/configure_boot.sh

Environment Variables#

The system manages environment variables through a .env file stored on the NAS mount. If the file doesn't exist, you'll be prompted to create it with these variables:

  • DYNAMICAL_SYSTEM_FOLDER: Where config, secrets and data are
  • DYNAMICAL_SYSTEM_ENV: Environment (prod/test/dev)

Variables are:

  • Loaded automatically on login via /etc/profile.d/machine-env.sh
  • Available system-wide through systemd services
  • Stored securely with 600 permissions

NAS Mount Configuration#

CIFS/SMB#

Credentials are stored in /etc/samba/credentials-<share> with secure permissions. The mount is configured in /etc/fstab for persistence.

NFS#

Standard NFS mount configuration in /etc/fstab with appropriate options for reliability.

Docker Configuration#

Rootless Docker is installed with:

  • User namespace isolation using the concept of sheets
  • Non-root daemon operation
  • Automatic startup via systemd user services
  • Docker Compose plugin included
  • Pasta networking backend (if available) for improved connectivity

Known Limitations#

Rootless Docker Networking:

  • Container outbound connectivity may be limited in rootless mode
  • If you experience issues pulling images or containers can't reach the internet:
    • Try using docker run --network host for containers that need network access
    • Consider using rootful Docker with sudo docker for full network capabilities
    • On networks with IPv4 restrictions, pasta backend provides better connectivity than slirp4netns

Boot Services#

The following systemd services are created:

  • machine-env-loader.service: Loads environment variables at boot
  • verify-nas-mount.service: Ensures NAS is mounted before loading env vars
  • docker-rootless.service: Starts Docker in user context
  • machine-startup.service: Handles overall boot initialization

Troubleshooting#

NAS Mount Issues#

# Check mount status
mount | grep <mount_point>

# Verify fstab entry
cat /etc/fstab

# Test mount manually
sudo mount <mount_point>

Docker Issues#

# Check Docker status
systemctl --user status docker

# Verify Docker context
docker context ls

# Test Docker
docker run hello-world

Environment Variables#

# Check loaded variables
env | grep <VAR_NAME>

# Verify .env file
cat <nas_mount>/.env

# Check profile script
cat /etc/profile.d/machine-env.sh

Security Notes#

  • NAS credentials are stored with 600 permissions
  • Docker runs in rootless mode for enhanced security
  • Environment variables containing secrets are handled securely
  • All scripts validate inputs and check prerequisites

Logs#

Setup logs are saved to /tmp/machine-setup-<timestamp>.log

License#

This project is provided as-is for automation purposes.