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 planIn 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 = 5State Management
Local state (development):
# Default - state stored in terraform.tfstateRemote 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 destroyModules
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-inventoryansible.cfg:
[defaults]
inventory = /usr/local/bin/fugoku-ansible-inventoryOr use directly:
ansible-playbook -i fugoku-ansible-inventory playbook.ymlThe 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-2Provisioning 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/appRun:
ansible-playbook playbook.ymlCreate 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.PrivateIPBest Practices
- Use version control - Store IaC in Git
- Remote state - Use Terraform Cloud or S3 backend
- Modules - Create reusable components
- Variables - Parameterize environments (dev, staging, prod)
- Secrets management - Use vaults (HashiCorp Vault, AWS Secrets Manager)
- State locking - Prevent concurrent modifications
- Plan before apply - Always review changes
- Tagging - Tag all resources for cost tracking and organization
- 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-approveGitLab 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:
- mainNext Steps: