mcpField
D
digitalocean-coder

digitalocean-coder

github.com/majesticlabs-devCloud & DevOps5064 installsUpdated 7w ago
Repository

About digitalocean-coder

digitalocean-coder is a skill with Terraform examples for configuring DigitalOcean infrastructure. It covers compute, networking, databases, storage, DNS, firewalls, and SSH keys.

Key features

  1. 01Configure VPCs and Droplets
  2. 02Set up reserved IPs
  3. 03Define firewalls and database access
  4. 04Provision PostgreSQL and Redis clusters
  5. 05Configure Spaces buckets and DNS
  6. 06Manage DigitalOcean SSH keys

Use cases

  1. 01Draft Terraform for a DigitalOcean app stack
  2. 02Configure network and firewall resources
  3. 03Set up managed databases and object storage

Install

Copy the command and run it in a terminal.

$npx skills add https://github.com/majesticlabs-dev/majestic-marketplace --skill digitalocean-coder

After installing, type/digitalocean-coderin Claude Code to confirm it loaded.

Bundled filesreferences/digitalocean-production-stack.mdreferences/digitalocean-sizes.md

Details

From the project README

Provider Setup

terraform {
  required_providers {
    digitalocean = {
      source  = "digitalocean/digitalocean"
      version = "~> 2.0"
    }
  }
}

provider "digitalocean" {
  # Uses DIGITALOCEAN_TOKEN env var
}

VPC (Virtual Private Cloud)

resource "digitalocean_vpc" "main" {
  name     = "${var.project}-${var.environment}-vpc"
  region   = var.region
  ip_range = "10.10.0.0/16"

  description = "VPC for ${var.project} ${var.environment}"
}

Droplets (Compute)

Basic Droplet
resource "digitalocean_droplet" "app" {
  name     = "${var.project}-${var.environment}-app"
  region   = var.region
  size     = var.droplet_size  # s-1vcpu-1gb, s-2vcpu-4gb, etc.
  image    = "ubuntu-22-04-x64"
  vpc_uuid = digitalocean_vpc.main.id

  ssh_keys   = var.ssh_key_ids
  monitoring = true
  ipv6       = false

  tags = [var.project, var.environment]
}
Droplet with Cloud-Init
resource "digitalocean_droplet" "app" {
  name     = "${var.project}-app"
  region   = var.region
  size     = "s-1vcpu-2gb"
  image    = "ubuntu-22-04-x64"
  vpc_uuid = digitalocean_vpc.main.id

  ssh_keys   = var.ssh_key_ids
  monitoring = true

  user_data = <<-EOT
    #cloud-config
    package_update: true
    packages:
      - docker.io
      - docker-compose-plugin
    users:
      - name: deploy
        groups: docker
        sudo: ALL=(ALL) NOPASSWD:ALL
        shell: /bin/bash
        ssh_authorized_keys:
          - ${var.deploy_ssh_key}
    runcmd:
      - systemctl enable --now docker
      - sed -i 's/PermitRootLogin yes/PermitRootLogin no/' /etc/ssh/sshd_config
      - systemctl restart sshd
  EOT

  tags = [var.project]
}

See references/digitalocean-sizes.md for droplet and database sizes.

Reserved IP (Static IP)

resource "digitalocean_reserved_ip" "app" {
  region = var.region
}

resource "digitalocean_reserved_ip_assignment" "app" {
  ip_address = digitalocean_reserved_ip.app.ip_address
  droplet_id = digitalocean_droplet.app.id
}

output "app_ip" {
  value = digitalocean_reserved_ip.app.ip_address
}

Firewall

Basic Web Server Firewall
resource "digitalocean_firewall" "web" {
  name = "${var.project}-web-firewall"

  droplet_ids = [digitalocean_droplet.app.id]

  inbound_rule {
    protocol         = "tcp"
    port_range       = "22"
    source_addresses = var.ssh_allowed_ips
  }

  inbound_rule {
    protocol         = "tcp"
    port_range       = "80"
    source_addresses = ["0.0.0.0/0", "::/0"]
  }

  inbound_rule {
    protocol         = "tcp"
    port_range       = "443"
    source_addresses = ["0.0.0.0/0", "::/0"]
  }

  outbound_rule {
    protocol              = "tcp"
    port_range            = "all"
    destination_addresses = ["0.0.0.0/0", "::/0"]
  }

  outbound_rule {
    protocol              = "udp"
    port_range            = "all"
    destination_addresses = ["0.0.0.0/0", "::/0"]
  }

  outbound_rule {
    protocol              = "icmp"
    destination_addresses = ["0.0.0.0/0", "::/0"]
  }
}
Dynamic IP Whitelist
variable "db_allowed_ips" {
  type        = list(string)
  default     = []
  description = "IPs allowed to access database directly"
}

resource "digitalocean_database_firewall" "postgres" {
  cluster_id = digitalocean_database_cluster.postgres.id

  rule {
    type  = "droplet"
    value = digitalocean_droplet.app.id
  }

  dynamic "rule" {
    for_each = var.db_allowed_ips
    content {
      type  = "ip_addr"
      value = rule.value
    }
  }
}

Managed Database

PostgreSQL Cluster
resource "digitalocean_database_cluster" "postgres" {
  name       = "${var.project}-${var.environment}-pg"
  engine     = "pg"
  version    = "16"
  size       = var.db_size  # db-s-1vcpu-1gb, db-s-2vcpu-4gb
  region     = var.region
  node_count = 1  # Increase for HA

  private_network_uuid = digitalocean_vpc.main.id

  tags = [var.project, var.environment]
}

resource "digitalocean_database_firewall" "postgres" {
  cluster_id = digitalocean_database_cluster.postgres.id

  rule {
    type  = "droplet"
    value = digitalocean_droplet.app.id
  }
}

output "database_uri" {
  value     = digitalocean_database_cluster.postgres.uri
  sensitive = true
}

output "database_private_uri" {
  value     = digitalocean_database_cluster.postgres.private_uri
  sensitive = true
}
Redis Cluster
resource "digitalocean_database_cluster" "redis" {
  name       = "${var.project}-${var.environment}-redis"
  engine     = "redis"
  version    = "7"
  size       = "db-s-1vcpu-1gb"
  region     = var.region
  node_count = 1

  private_network_uuid = digitalocean_vpc.main.id
  tags                 = [var.project]
}

Spaces (Object Storage)

resource "digitalocean_spaces_bucket" "assets" {
  name   = "${var.project}-assets"
  region = var.spaces_region  # nyc3, sfo3, ams3, sgp1, fra1

  acl = "private"
}

resource "digitalocean_spaces_bucket_cors_configuration" "assets" {
  bucket = digitalocean_spaces_bucket.assets.id
  region = var.spaces_region

  cors_rule {
    allowed_headers = ["*"]
    allowed_methods = ["GET", "PUT", "POST"]
    allowed_origins = ["https://${var.domain}"]
    max_age_seconds = 3600
  }
}

output "spaces_endpoint" {
  value = digitalocean_spaces_bucket.assets.bucket_domain_name
}

DNS Records

resource "digitalocean_domain" "main" {
  name = var.domain
}

resource "digitalocean_record" "app" {
  domain = digitalocean_domain.main.id
  type   = "A"
  name   = "@"
  value  = digitalocean_reserved_ip.app.ip_address
  ttl    = 300
}

resource "digitalocean_record" "www" {
  domain = digitalocean_domain.main.id
  type   = "CNAME"
  name   = "www"
  value  = "@"
  ttl    = 300
}

SSH Keys

data "digitalocean_ssh_key" "deploy" {
  name = "deploy-key"
}

resource "digitalocean_ssh_key" "deploy" {
  name       = "${var.project}-deploy"
  public_key = file("~/.ssh/deploy.pub")
}

See references/digitalocean-production-stack.md for a complete production setup with VPC, droplet, firewall, database, and outputs.

References

Comments

Markdown supported