Как запустить GPU Runtime для Google Collab с помощью Terraform

Работал я как‑то над fine‑tuning для одной модели. Потенциала моих GPU в домашней лаборатории (home lab) для такой задачи было недостаточно. Сам fine‑tuning VLM это вообще отдельный разговор, и вопрос его целесообразности стоит обсудить отдельно, но для него мне потребовалась внешняя видеокарта.

Я расскажу ниже, как подключить GPU от стороннего провайдера себе в Google Collab.

На рынке сейчас есть три вида игроков:

  • облака (в РФ это, например, компания‑такси, банк и социальная сеть);
  • специализированные хостинг‑провайдеры;
  • P2P‑маркетплейсы, где любой владелец видеокарты может сдать её в аренду.

Облака - очень дорогое решение и уже давно совсем не недружелюбны с точки зрения UX. Любой специализированный хостинг‑провайдер для GPU, каким бы посредственным дизайном он ни обладал, всегда будет более удобен в использовании. Облака давно создали целый зверинец сервисов, разных правил и усложнений. И хотя они во многом похожи, зачем‑то соревнуются в том, у кого будет более интересный UI. Помимо перегруженности интерфейса, облака имеют абсолютно оборзевшие тарифы на услуги.

Маркетеплейсов p2p в РФ нету. Ждем когда Дуров уже запустит сервис Cocoon, вроде собирался.

Поэтому мой выбор обычно падает на один иностранный p2p (hyperbolic) или на пару наших хостинг провайдеров (к примеру, immers.cloud — но это не важно для данной статьи и не является рекомендацией).

Кстати нормальная цена для H100 2$ и для H200 2.5$ на февраль 2026 года. Это как бы говорит о том, что, если вдруг решите обучить свою LLM, которая попала бы в топ‑100 по бенчмаркам, потребуется порядка 2 миллионов долларов.

Моя цель — запустить Jupyter Notebook на такой машине и пробросить порт Jupyter‑сервера на мой localhost:8888 (или на другой порт). Затем, когда мы сможем работать в этом Jupyter через http://localhost:8888, останется в интерфейсе Google Colab в настройках runtime (там, где кнопка Connect) указать Connect to a local Runtime и прописать путь к Jupyter с нужным токеном. В процессе будет несколько нюансов, но концепция проще некуда.

Через UI хостинг провайдера GPU нам нужно получить:

  • ip
  • username
  • .pem / private key

Warning

Образ нужно использовать Debian и с уже установленной CUDA

Для работы на удалённой машине мы даже не будем заходить на неё вручную — я буду использовать OpenTofu. Это инструмент, который полноценно заменяет Terraform от HashiCorp.

Для установки OpenTofu, я использую mise и вам советую.

mise use --global opentofu

А в моем коде, который можно скачать по ссылке, opentofu будет прописан в mise.toml и при установленном mise, вам даже запускать эту команду не надо будет, а tofu будет доступен при переходе в папку с кодом. Нужно выполнить mise trust в папке, чтобы файл mise.toml стал доверенным.

Начнем с main.tf
resource "random_password" "jupyter_token" {
    length  = 32
    special = false
    override_special = ""
  }

resource "null_resource" "jupyter" {
  connection {
    type        = "ssh"
    host        = var.server_ip
    user        = var.username
    private_key = file(var.ssh_key_path)
    timeout     = "5m"
  }

  provisioner "file" {
    content = <<-EOF
      [Unit]
      Description=Jupyter Notebook Service
      After=network.target

      [Service]
      Type=simple
      User=${var.username}
      WorkingDirectory=/home/${var.username}/notebooks
      ExecStart=/home/${var.username}/.jupyter-env/bin/jupyter-notebook --no-browser --ip=0.0.0.0 --port=${var.jupyter_port} --notebook-dir=/home/${var.username}/notebooks --NotebookApp.token=${random_password.jupyter_token.result} --ServerApp.allow_origin='https://colab.research.google.com' --ServerApp.port_retries=0
      Restart=always
      RestartSec=10

      [Install]
      WantedBy=multi-user.target
    EOF
    destination = "/tmp/jupyter.service"
  }

  provisioner "remote-exec" {
    inline = [
      "curl -LsSf https://astral.sh/uv/install.sh | sh",
      "export PATH=\"$HOME/.local/bin:$PATH\"",
      "mkdir -p ~/.jupyter ~/notebooks",
      "uv venv --clear ~/.jupyter-env",
      "uv pip install --python ~/.jupyter-env/bin/python notebook torch numpy",
      
      "sudo mv /tmp/jupyter.service /etc/systemd/system/jupyter.service",
      "sudo systemctl daemon-reload",
      "sudo systemctl enable jupyter",
      "sudo systemctl restart jupyter",
      "sudo systemctl status jupyter --no-pager",
    ]
  }
}

resource "null_resource" "configure_firewall" {
  depends_on = [null_resource.jupyter]

  triggers = {
    jupyter_port = var.jupyter_port
  }

  connection {
    type        = "ssh"
    host        = var.server_ip
    user        = var.username
    private_key = file(var.ssh_key_path)
    timeout     = "5m"
  }

  provisioner "remote-exec" {
    inline = [
      "sudo apt-get update -qq",
      "sudo apt-get install -y ufw fail2ban",
      "sudo ufw --force reset",
      "sudo ufw allow 22/tcp",
      "sudo ufw default deny incoming",
      "sudo ufw default allow outgoing",
      "sudo ufw --force enable",
      "sudo ufw status verbose",
      "sudo systemctl enable fail2ban",
      "sudo systemctl restart fail2ban"
    ]
  }
}

output "jupyter_instruction" {
  description = """
    You should do port forwarding:
    ssh -i ${var.ssh_key_path} ${var.username}@${var.server_ip} -L ${var.jupyter_port}:localhost:${var.jupyter_port}"""
  value = nonsensitive("http://${var.server_ip}:${var.jupyter_port}/?token=${random_password.jupyter_token.result}")
}

Важно для нашей задачи — скрипт запуска Jupyter:

/home/${var.username}/.jupyter-env/bin/jupyter-notebook --no-browser --ip=0.0.0.0 --port=${var.jupyter_port} --notebook-dir=/home/${var.username}/notebooks --NotebookApp.token=${random_password.jupyter_token.result} --ServerApp.allow_origin='https://colab.research.google.com' --ServerApp.port_retries=0

Мы должны прописать allow_origin для google collab. В остальном скрипт не претендует на что‑то большее, чем просто запуск сервиса Jupyter на Debian. Мы открываем только SSH‑порт и блокируем попытки подключения по SSH с неправильным ключом по IP. Вся прелесть в том, что один раз написанный скрипт OpenTofu даёт возможность поднять runtime для Google Colab в любой момент — быстро и без заморочек.

Tip

Так как нам нужен Terraform Registry, если вы проживаете в РФ, следует использовать registry mirror:

Либо от нашего оператора такси, либо от банка:

provider_installation {
  network_mirror {
	# https://terraform.cloud.ru/
    url = "https://terraform-mirror.yandexcloud.net/"
    include = ["registry.terraform.io/*/*"]
  }
  direct {
    exclude = ["registry.terraform.io/*/*"]
  }
}

Запускаем GPU Runtime

Как проходит запуск инфраструктуры:

  • Перешли в папку с кодом инфраструктуры
    • Благодаря mise инструмент tofu автоматически подвязывается в PATH — то есть команда tofu становится доступна в консоли.
  • Обновим terraform.tfvars или создадим его
server_ip      = "ip address"
username       = "ubuntu"
ssh_key_path   = "private.pem"
jupyter_port   = 8899
  • Смотрим доступные команды: mise tasks
  • Инициализируем tofu mise run init
  • Применяем конфигурацию на удалённом GPU‑сервере: mise run apply

Ждем...

В ответе получим строчку c localhost и token, которая если бы мы были на машине с нашей GPU, то она открыла бы Jupyter Notebook. Но мы у себя на машине, а GPU сервер имеет только один открытый порт и это ssh.

Нам осталось пробросить порт на локальную машину:

ssh -i private.pem ubuntu@xxx.xxx.xxx.xxx -L 8888:localhost:8888

Копируем строку с токеном и пробуем открыть в браузере: sh http://${var.server_ip}:${var.jupyter_port}/?token=${random_password.jupyter_token.result

Обе строки — для проброски порта и для доступа к Jupyter Notebook — должны быть в ответе на команду apply, так что вручную их редактировать не нужно.

Если в браузере всё открывается, прописываем этот сервер как local runtime в интерфейсе Google Colab:

Попробуйте выполнить простой Python‑скрипт в Google Collab:

import torch
print(torch.cuda.get_device_name(0))

Да, я запустил платный Tesla T4, хотя Google Colab предоставляет его бесплатно — но это сделано исключительно для скриншота. Стоимость использования Tesla T4 — около десяти рублей в час.

Полный код доступен по ссылке для всех, кто зарегистрировался в моём блоге.