FugokuFugoku Docs
Mask

Infrastructure as Code

Manage Fugoku infrastructure with Terraform, Ansible, and other IaC tools

Infrastructure as Code

Manage Fugoku infrastructure declaratively using Terraform, Ansible, Pulumi, and other IaC tools.

Terraform Provider

Installation

Terraform Registry:

terraform {
  required_providers {
    fugoku = {
      source  = "fugoku/fugoku"
      version = "~> 1.0"
    }
  }
}

provider "fugoku" {
  api_token = var.fugoku_token
  # Or use FUGOKU_API_TOKEN environment variable
}

Manual:

# Download provider
curl -LO https://github.com/fugoku/terraform-provider-fugoku/releases/download/v1.0.0/terraform-provider-fugoku_1.0.0_darwin_amd64.zip

# Extract to Terraform plugins directory
unzip terraform-provider-fugoku_*.zip -d ~/.terraform.d/plugins/

Authentication

Environment variable (recommended):

export FUGOKU_API_TOKEN="fgk_abc123..."
terraform plan

In provider config:

provider "fugoku" {
  api_token = "fgk_abc123..."  # Not recommended - use variables
}

Using variables:

# variables.tf
variable "fugoku_token" {
  type      = string
  sensitive = true
}

# Provider configuration
provider "fugoku" {
  api_token = var.fugoku_token
}
# terraform.tfvars (add to .gitignore!)
fugoku_token = "fgk_abc123..."

Resources

Compute Instance

resource "fugoku_instance" "web" {
  name   = "web-1"
  region = "lagos-1"
  plan   = "standard-2"
  image  = "ubuntu-22.04"
  
  ssh_keys = [fugoku_ssh_key.deployer.id]
  
  tags = [
    "production",
    "web"
  ]
  
  user_data = file("${path.module}/cloud-init.yaml")
  
  backups_enabled = true
  
  private_networks = [
    fugoku_network.backend.id
  ]
}

output "web_ip" {
  value = fugoku_instance.web.public_ip
}

SSH Key

resource "fugoku_ssh_key" "deployer" {
  name       = "deployer"
  public_key = file("~/.ssh/id_rsa.pub")
}

Block Volume

resource "fugoku_volume" "data" {
  name      = "app-data"
  region    = "lagos-1"
  size_gb   = 100
  
  snapshot_schedule = {
    enabled   = true
    frequency = "daily"
    retention = 7
    time      = "02:00"
  }
}

resource "fugoku_volume_attachment" "data_attach" {
  volume_id   = fugoku_volume.data.id
  instance_id = fugoku_instance.web.id
}

Private Network

resource "fugoku_network" "backend" {
  name         = "backend-net"
  region       = "lagos-1"
  subnet       = "10.10.0.0/24"
  dhcp_enabled = true
}

resource "fugoku_network_attachment" "web_backend" {
  network_id  = fugoku_network.backend.id
  instance_id = fugoku_instance.web.id
}

Floating IP

resource "fugoku_floating_ip" "web" {
  region = "lagos-1"
}

resource "fugoku_floating_ip_assignment" "web" {
  floating_ip_id = fugoku_floating_ip.web.id
  instance_id    = fugoku_instance.web.id
}

output "floating_ip" {
  value = fugoku_floating_ip.web.ip_address
}

Load Balancer

resource "fugoku_load_balancer" "api" {
  name      = "api-lb"
  region    = "lagos-1"
  algorithm = "least_connections"
  
  listener {
    protocol      = "http"
    port          = 80
    backend_port  = 8080
  }
  
  health_check {
    path                = "/health"
    interval            = 10
    timeout             = 5
    unhealthy_threshold = 3
    healthy_threshold   = 2
  }
}

resource "fugoku_load_balancer_backend" "api_instances" {
  count = 3
  
  load_balancer_id = fugoku_load_balancer.api.id
  instance_id      = fugoku_instance.api[count.index].id
  weight           = 100
}

Firewall Rule

resource "fugoku_firewall_rule" "web_http" {
  instance_id = fugoku_instance.web.id
  direction   = "inbound"
  protocol    = "tcp"
  port        = 80
  source      = "0.0.0.0/0"
}

resource "fugoku_firewall_rule" "web_https" {
  instance_id = fugoku_instance.web.id
  direction   = "inbound"
  protocol    = "tcp"
  port        = 443
  source      = "0.0.0.0/0"
}

Data Sources

# Get available images
data "fugoku_images" "ubuntu" {
  os = "ubuntu"
}

# Use latest Ubuntu image
resource "fugoku_instance" "web" {
  image = data.fugoku_images.ubuntu.images[0].id
  # ...
}

# Get account info
data "fugoku_account" "current" {}

output "account_email" {
  value = data.fugoku_account.current.email
}

# Get available plans
data "fugoku_plans" "all" {}

# Get regions
data "fugoku_regions" "all" {}

Example: Complete Stack

# main.tf

terraform {
  required_providers {
    fugoku = {
      source  = "fugoku/fugoku"
      version = "~> 1.0"
    }
  }
}

provider "fugoku" {
  api_token = var.fugoku_token
}

# SSH Key
resource "fugoku_ssh_key" "deployer" {
  name       = "deployer"
  public_key = file("~/.ssh/id_rsa.pub")
}

# Private Network
resource "fugoku_network" "app" {
  name   = "app-network"
  region = var.region
  subnet = "10.10.0.0/24"
}

# Database Instance
resource "fugoku_instance" "database" {
  name   = "${var.project}-database"
  region = var.region
  plan   = "ram-4"
  image  = "ubuntu-22.04"
  
  ssh_keys         = [fugoku_ssh_key.deployer.id]
  private_networks = [fugoku_network.app.id]
  backups_enabled  = true
  
  tags = [var.project, "database", var.environment]
}

# App Instances
resource "fugoku_instance" "app" {
  count = var.app_instance_count
  
  name   = "${var.project}-app-${count.index + 1}"
  region = var.region
  plan   = "standard-2"
  image  = "ubuntu-22.04"
  
  ssh_keys         = [fugoku_ssh_key.deployer.id]
  private_networks = [fugoku_network.app.id]
  
  user_data = templatefile("${path.module}/app-init.yaml", {
    db_host = fugoku_instance.database.private_ip
  })
  
  tags = [var.project, "app", var.environment]
}

# Load Balancer
resource "fugoku_load_balancer" "app" {
  name      = "${var.project}-lb"
  region    = var.region
  algorithm = "least_connections"
  
  listener {
    protocol     = "http"
    port         = 80
    backend_port = 3000
  }
  
  health_check {
    path     = "/health"
    interval = 10
    timeout  = 5
  }
}

resource "fugoku_load_balancer_backend" "app" {
  count = var.app_instance_count
  
  load_balancer_id = fugoku_load_balancer.app.id
  instance_id      = fugoku_instance.app[count.index].id
}

# Floating IP for LB
resource "fugoku_floating_ip" "lb" {
  region = var.region
}

resource "fugoku_floating_ip_assignment" "lb" {
  floating_ip_id = fugoku_floating_ip.lb.id
  instance_id    = fugoku_load_balancer.app.instance_id
}

# Outputs
output "load_balancer_ip" {
  value = fugoku_floating_ip.lb.ip_address
}

output "database_private_ip" {
  value = fugoku_instance.database.private_ip
}

output "app_instances" {
  value = {
    for instance in fugoku_instance.app :
    instance.name => instance.public_ip
  }
}
# variables.tf

variable "fugoku_token" {
  type      = string
  sensitive = true
}

variable "project" {
  type    = string
  default = "myapp"
}

variable "environment" {
  type    = string
  default = "production"
}

variable "region" {
  type    = string
  default = "lagos-1"
}

variable "app_instance_count" {
  type    = number
  default = 3
}
# terraform.tfvars

fugoku_token       = "fgk_abc123..."
project            = "ecommerce"
environment        = "production"
region             = "lagos-1"
app_instance_count = 5

State Management

Local state (development):

# Default - state stored in terraform.tfstate

Remote state (production):

terraform {
  backend "s3" {
    bucket = "mycompany-terraform-state"
    key    = "fugoku/production.tfstate"
    region = "us-east-1"
  }
}

Terraform Cloud:

terraform {
  cloud {
    organization = "mycompany"
    
    workspaces {
      name = "fugoku-production"
    }
  }
}

Workflow

# Initialize
terraform init

# Plan changes
terraform plan

# Apply changes
terraform apply

# Show current state
terraform show

# Destroy all resources
terraform destroy

Modules

Create reusable modules for common patterns.

Example module:

# modules/web-tier/main.tf

variable "name" {
  type = string
}

variable "region" {
  type = string
}

variable "instance_count" {
  type    = number
  default = 2
}

resource "fugoku_instance" "web" {
  count = var.instance_count
  
  name   = "${var.name}-${count.index + 1}"
  region = var.region
  plan   = "standard-2"
  image  = "ubuntu-22.04"
}

resource "fugoku_load_balancer" "web" {
  name   = "${var.name}-lb"
  region = var.region
  
  listener {
    protocol     = "http"
    port         = 80
    backend_port = 80
  }
}

output "lb_ip" {
  value = fugoku_load_balancer.web.ip_address
}

Use module:

module "frontend" {
  source = "./modules/web-tier"
  
  name           = "frontend"
  region         = "lagos-1"
  instance_count = 3
}

output "frontend_ip" {
  value = module.frontend.lb_ip
}

Ansible

Dynamic Inventory

Use Fugoku CLI to generate Ansible inventory:

# Install fugoku-ansible-inventory script
curl -sSL https://cli.fugoku.com/ansible-inventory.py > /usr/local/bin/fugoku-ansible-inventory
chmod +x /usr/local/bin/fugoku-ansible-inventory

ansible.cfg:

[defaults]
inventory = /usr/local/bin/fugoku-ansible-inventory

Or use directly:

ansible-playbook -i fugoku-ansible-inventory playbook.yml

The inventory script groups instances by:

  • Tag
  • Region
  • Plan
  • Status
# Example groups:
tag_production:
  - web-1
  - web-2
  
region_lagos_1:
  - web-1
  - db-1
  
plan_standard_2:
  - web-1
  - web-2

Provisioning Playbook

# playbook.yml

- name: Configure web servers
  hosts: tag_web
  become: yes
  
  tasks:
    - name: Update apt cache
      apt:
        update_cache: yes
    
    - name: Install Nginx
      apt:
        name: nginx
        state: present
    
    - name: Start Nginx
      systemd:
        name: nginx
        state: started
        enabled: yes
    
    - name: Deploy application
      git:
        repo: https://github.com/myorg/app.git
        dest: /var/www/app
        version: main
    
    - name: Install dependencies
      command: npm install
      args:
        chdir: /var/www/app

Run:

ansible-playbook playbook.yml

Create Instances with Ansible

# create-infrastructure.yml

- name: Provision Fugoku infrastructure
  hosts: localhost
  connection: local
  
  vars:
    fugoku_token: "{{ lookup('env', 'FUGOKU_API_TOKEN') }}"
  
  tasks:
    - name: Create instances
      uri:
        url: https://api.fugoku.com/v1/instances
        method: POST
        headers:
          Authorization: "Bearer {{ fugoku_token }}"
          Content-Type: application/json
        body_format: json
        body:
          name: "web-{{ item }}"
          region: lagos-1
          plan: standard-2
          image: ubuntu-22.04
        status_code: 201
      loop: [1, 2, 3]
      register: instances
    
    - name: Wait for instances to be running
      uri:
        url: "https://api.fugoku.com/v1/instances/{{ item.json.data.id }}"
        headers:
          Authorization: "Bearer {{ fugoku_token }}"
      register: result
      until: result.json.data.status == "running"
      retries: 20
      delay: 10
      loop: "{{ instances.results }}"

Pulumi

TypeScript

// index.ts

import * as fugoku from "@pulumi/fugoku";

// SSH Key
const deployKey = new fugoku.SshKey("deploy-key", {
  name: "deployer",
  publicKey: fs.readFileSync(path.join(os.homedir(), ".ssh/id_rsa.pub"), "utf8"),
});

// Private Network
const appNetwork = new fugoku.Network("app-network", {
  name: "app-net",
  region: "lagos-1",
  subnet: "10.10.0.0/24",
});

// Database Instance
const database = new fugoku.Instance("database", {
  name: "postgres-1",
  region: "lagos-1",
  plan: "ram-4",
  image: "ubuntu-22.04",
  sshKeys: [deployKey.id],
  privateNetworks: [appNetwork.id],
  backupsEnabled: true,
  tags: ["production", "database"],
});

// App Instances
const appInstances: fugoku.Instance[] = [];
for (let i = 0; i < 3; i++) {
  appInstances.push(new fugoku.Instance(`app-${i}`, {
    name: `app-${i + 1}`,
    region: "lagos-1",
    plan: "standard-2",
    image: "ubuntu-22.04",
    sshKeys: [deployKey.id],
    privateNetworks: [appNetwork.id],
    tags: ["production", "app"],
  }));
}

// Load Balancer
const loadBalancer = new fugoku.LoadBalancer("app-lb", {
  name: "app-lb",
  region: "lagos-1",
  algorithm: "least_connections",
  listener: {
    protocol: "http",
    port: 80,
    backendPort: 3000,
  },
  healthCheck: {
    path: "/health",
    interval: 10,
    timeout: 5,
  },
});

// Add backends
appInstances.forEach((instance, i) => {
  new fugoku.LoadBalancerBackend(`backend-${i}`, {
    loadBalancerId: loadBalancer.id,
    instanceId: instance.id,
  });
});

// Outputs
export const lbIp = loadBalancer.ipAddress;
export const dbPrivateIp = database.privateIp;

Python

# __main__.py

import pulumi
import pulumi_fugoku as fugoku

# SSH Key
deploy_key = fugoku.SshKey("deploy-key",
    name="deployer",
    public_key=open(os.path.expanduser("~/.ssh/id_rsa.pub")).read()
)

# Database
database = fugoku.Instance("database",
    name="postgres-1",
    region="lagos-1",
    plan="ram-4",
    image="ubuntu-22.04",
    ssh_keys=[deploy_key.id],
    backups_enabled=True,
    tags=["production", "database"]
)

# App Instances
app_instances = []
for i in range(3):
    app = fugoku.Instance(f"app-{i}",
        name=f"app-{i+1}",
        region="lagos-1",
        plan="standard-2",
        image="ubuntu-22.04",
        ssh_keys=[deploy_key.id],
        tags=["production", "app"]
    )
    app_instances.append(app)

# Outputs
pulumi.export("database_ip", database.private_ip)
pulumi.export("app_ips", [inst.public_ip for inst in app_instances])

CloudFormation-Style (YAML)

While not officially supported, you can use YAML with tools like cfn-lint for validation:

# fugoku-stack.yaml

Resources:
  DeployKey:
    Type: Fugoku::SSH::Key
    Properties:
      Name: deployer
      PublicKey: !GetFile ~/.ssh/id_rsa.pub
  
  AppNetwork:
    Type: Fugoku::Network
    Properties:
      Name: app-net
      Region: lagos-1
      Subnet: 10.10.0.0/24
  
  Database:
    Type: Fugoku::Instance
    Properties:
      Name: postgres-1
      Region: lagos-1
      Plan: ram-4
      Image: ubuntu-22.04
      SSHKeys:
        - !Ref DeployKey
      PrivateNetworks:
        - !Ref AppNetwork

Outputs:
  DatabaseIP:
    Value: !GetAtt Database.PrivateIP

Best Practices

  1. Use version control - Store IaC in Git
  2. Remote state - Use Terraform Cloud or S3 backend
  3. Modules - Create reusable components
  4. Variables - Parameterize environments (dev, staging, prod)
  5. Secrets management - Use vaults (HashiCorp Vault, AWS Secrets Manager)
  6. State locking - Prevent concurrent modifications
  7. Plan before apply - Always review changes
  8. Tagging - Tag all resources for cost tracking and organization
  9. Documentation - Comment complex logic

CI/CD Integration

GitHub Actions

# .github/workflows/terraform.yml

name: Terraform

on:
  push:
    branches: [main]
  pull_request:

jobs:
  terraform:
    runs-on: ubuntu-latest
    
    steps:
      - uses: actions/checkout@v3
      
      - name: Setup Terraform
        uses: hashicorp/setup-terraform@v2
        with:
          terraform_version: 1.5.0
      
      - name: Terraform Init
        env:
          FUGOKU_API_TOKEN: ${{ secrets.FUGOKU_API_TOKEN }}
        run: terraform init
      
      - name: Terraform Plan
        env:
          FUGOKU_API_TOKEN: ${{ secrets.FUGOKU_API_TOKEN }}
        run: terraform plan
      
      - name: Terraform Apply
        if: github.ref == 'refs/heads/main'
        env:
          FUGOKU_API_TOKEN: ${{ secrets.FUGOKU_API_TOKEN }}
        run: terraform apply -auto-approve

GitLab CI

# .gitlab-ci.yml

stages:
  - validate
  - plan
  - apply

variables:
  TF_ROOT: ${CI_PROJECT_DIR}

terraform:validate:
  stage: validate
  image: hashicorp/terraform:1.5
  script:
    - cd ${TF_ROOT}
    - terraform init
    - terraform validate

terraform:plan:
  stage: plan
  image: hashicorp/terraform:1.5
  script:
    - cd ${TF_ROOT}
    - terraform init
    - terraform plan -out=plan.tfplan
  artifacts:
    paths:
      - plan.tfplan

terraform:apply:
  stage: apply
  image: hashicorp/terraform:1.5
  script:
    - cd ${TF_ROOT}
    - terraform init
    - terraform apply plan.tfplan
  when: manual
  only:
    - main

Next Steps:

On this page