Floci, OpenTofu and mise homelab setup

Overview

This lab runs Floci and Floci-AZ in Docker on docker-lab, while OpenTofu and the Azure CLI are installed through mise on the remote Fedora workstation workstation-lab.

The aim is to provision emulated Azure resources from a separate machine, without running OpenTofu inside the Docker containers or signing into real Azure.

workstation-lab (Fedora)
  +-- mise
  |   +-- OpenTofu
  |   +-- Azure CLI
  +-- OpenTofu + AzureRM provider
         |
         | HTTPS (TLS), port 4577
         v
docker-lab (10.0.0.100)
  +-- Docker Compose
      +-- floci       -> port 4566 (AWS emulator)
      +-- floci-az    -> port 4577 (Azure emulator)

Lab only: Addresses, credentials, and example subscription/tenant IDs below are for local emulation, not production Azure.

1. Docker Compose on docker-lab

The setup below combines the AWS-compatible Floci service and Azure-compatible Floci-AZ service in one docker-compose.yml.

services:
  floci:
    image: floci/floci:latest
    container_name: floci
    restart: unless-stopped
    ports:
      - "4566:4566"
    environment:
      FLOCI_RUN_AS_ROOT: "true"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - ./data:/app/data
 
  floci-az:
    image: floci/floci-az:latest
    container_name: floci-az
    restart: unless-stopped
    ports:
      - "4577:4577"
    environment:
      FLOCI_AZ_BASE_URL: "https://10.0.0.100:4577"
      FLOCI_AZ_TLS_ENABLED: "true"
      FLOCI_AZ_HOSTNAME: "10.0.0.100"
      FLOCI_AZ_SERVICES_FUNCTIONS_ENABLED: "false"
    volumes:
      - ./data:/app/data

The Floci-AZ environment variables are important:

VariablePurpose
FLOCI_AZ_BASE_URLAdvertises the remotely reachable HTTPS endpoint of the Azure emulator.
FLOCI_AZ_TLS_ENABLEDEnables TLS, needed for the AzureRM endpoint discovery setup used here.
FLOCI_AZ_HOSTNAMESets the hostname/IP used for the local endpoint/certificate setup.
FLOCI_AZ_SERVICES_FUNCTIONS_ENABLEDDisables Functions emulation for this lab.

From the Docker Compose directory on docker-lab:

docker compose up -d
docker compose ps

If the same host-mounted ./data directory is used by both services, check persistence and permissions independently when upgrading. The current configuration reflects the lab setup, rather than a production deployment design.

2. Confirm access from workstation-lab

Floci-AZ is exposed on 10.0.0.100:4577. From Fedora:

curl http://10.0.0.100:4577/health
curl -k "https://10.0.0.100:4577/metadata/endpoints?api-version=2022-09-01"

The -k flag is only for this initial connectivity check: it bypasses TLS certificate verification. It is not needed once the certificate is configured for OpenTofu below.

3. Download the Floci-AZ TLS certificate

From the OpenTofu project directory on workstation-lab:

cd ~/github/programming/terraform/lab/hub_spoke_mgmt
curl -fsS http://10.0.0.100:4577/_floci/tls-cert -o floci-az.crt

The certificate is generated/exposed by the local emulator. Keep it under the project directory so the mise configuration can reference it.

Optional check:

openssl x509 -in floci-az.crt -noout -subject -issuer -dates

Security note: Only trust this certificate after verifying it comes from your own Floci-AZ instance. If the emulator regenerates the certificate, download the new copy.

4. Install OpenTofu and Azure CLI using mise

Both tools were installed via mise on Fedora. Verify the current environment:

mise ls
which tofu
which az
tofu version
az version

Example Azure CLI path:

~/.local/share/mise/installs/azure-cli/2.91.0/bin/az

The Azure CLI is present, but az login is not required for this emulator: the AzureRM provider uses the lab credentials configured below instead of Azure CLI authentication.

5. Project-local mise configuration

In the OpenTofu project root, create or update mise.toml:

[env]
SSL_CERT_FILE = "{{config_root}}/floci-az.crt"

This is the chosen option for this lab. With mise activated for your shell, it supplies the certificate path whenever you work in the project, so there is no need to prefix every command with SSL_CERT_FILE=....

Check:

mise trust          # only if mise asks you to trust this project config
mise env            # inspect mise's computed environment
printf '%s\n' "$SSL_CERT_FILE"

If the variable does not appear, ensure mise shell activation is configured, or run mise exec -- tofu plan to force execution inside the mise environment.

SSL_CERT_FILE can change which CA certificates other programs trust in the same shell. Keep it scoped to this lab, rather than putting it in a global shell profile. A self-signed local certificate may not include public CA roots.

6. Configure the AzureRM provider for Floci-AZ

OpenTofu still resolves the AzureRM provider from the Terraform provider registry, but the provider is configured to discover Azure endpoints from Floci-AZ instead of public Azure.

Example main.tf provider configuration:

terraform {
  required_providers {
    azurerm = {
      source  = "hashicorp/azurerm"
      version = "~> 4.0"
    }
  }
}
 
provider "azurerm" {
  features {}
 
  metadata_host = "10.0.0.100:4577"
 
  subscription_id = "00000000-0000-0000-0000-000000000001"
  tenant_id       = "00000000-0000-0000-0000-000000000002"
  client_id       = "00000000-0000-0000-0000-000000000003"
  client_secret   = "<LOCAL_EMULATOR_CLIENT_SECRET>"
 
  use_cli = false
 
  resource_provider_registrations = "none"
}

Key settings:

SettingWhy it matters
metadata_hostPoints AzureRM endpoint discovery at the remote Floci-AZ service.
subscription_id, tenant_id, client_id, client_secretLab-only identity values, replacing a real Azure login.
use_cli = falseStops AzureRM from trying to authenticate through az login.
resource_provider_registrations = "none"Avoids automatic Azure resource provider registrations.

The initial error (Please run 'az login') occurred because AzureRM was using Azure CLI authentication rather than this emulator-specific configuration.

7. Minimal test: resource group, VNet and subnet

Add these resources to your Terraform/OpenTofu configuration:

resource "azurerm_resource_group" "lab" {
  name     = "rg-floci-lab"
  location = "westeurope"
}
 
resource "azurerm_virtual_network" "hub" {
  name                = "vnet-hub"
  location            = azurerm_resource_group.lab.location
  resource_group_name = azurerm_resource_group.lab.name
  address_space       = ["10.0.0.0/16"]
}
 
resource "azurerm_subnet" "management" {
  name                 = "snet-management"
  resource_group_name  = azurerm_resource_group.lab.name
  virtual_network_name = azurerm_virtual_network.hub.name
  address_prefixes     = ["10.0.1.0/24"]
}

Run from workstation-lab in the project directory:

tofu init
tofu validate
tofu plan
tofu apply

Result in this lab: tofu plan and tofu apply worked when the Floci certificate was supplied. The mise configuration makes that certificate environment variable automatic for the project.

To remove test resources:

tofu destroy

8. Troubleshooting

SymptomCheck
Please run 'az login'Ensure the Floci-specific provider block is being loaded, use_cli = false, and lab credentials are configured.
x509: certificate signed by unknown authorityCheck SSL_CERT_FILE, the location/content of floci-az.crt, and whether the emulator regenerated its certificate.
Certificate hostname/IP mismatchEnsure the certificate SAN includes 10.0.0.100; setting a hostname in Compose alone does not fix an already generated certificate.
Connection refused / timeoutCheck docker compose ps, port 4577, firewall rules, and Fedora-to-docker-lab routing.
SSL_CERT_FILE is emptyConfirm shell activation, mise trust, or try mise exec -- tofu plan.
tofu plan works but a resource fails on applyThe emulator may not implement every AzureRM resource or API operation. Test resources incrementally.

9. Quick-reference commands

Docker host (docker-lab):

docker compose up -d
docker compose logs -f floci-az

OpenTofu workstation (workstation-lab):

cd ~/github/programming/terraform/lab/hub_spoke_mgmt
printf '%s\n' "$SSL_CERT_FILE"
tofu fmt
tofu init
tofu validate
tofu plan
tofu apply

If the Floci TLS certificate changes:

curl -fsS http://10.0.0.100:4577/_floci/tls-cert -o floci-az.crt

Notes and limitations

  • Floci-AZ simulates Azure management APIs; it does not necessarily provide real cloud packet forwarding, routing or network infrastructure.
  • Resource support depends on the version of Floci-AZ and AzureRM.
  • Treat the OpenTofu state file separately from the emulator’s persistence; a container reset can leave them out of sync.
  • Keep local state files and any genuine secrets out of Git (.terraform/, *.tfstate, *.tfstate.*, etc.).
  • If your host IP changes, update Compose, the provider’s metadata_host, and regenerate/retrieve a certificate valid for the new endpoint.