fix
This commit is contained in:
@@ -36,7 +36,7 @@ resource "coder_app" "terminal" {
|
||||
}
|
||||
|
||||
# =============================================================================
|
||||
# Service Port Forwarding for Docker Container Access
|
||||
# Service Port Forwarding for Docker Container Access
|
||||
# Note: Using direct container URLs since containers are on same Docker network
|
||||
# =============================================================================
|
||||
|
||||
@@ -76,7 +76,7 @@ resource "coder_app" "qdrant" {
|
||||
order = 11
|
||||
|
||||
healthcheck {
|
||||
url = "http://qdrant-${local.workspace_id}:6333/api/cluster"
|
||||
url = "http://qdrant-${local.workspace_id}:6333/health" # Use proper health endpoint
|
||||
interval = 30
|
||||
threshold = 10
|
||||
}
|
||||
@@ -270,4 +270,4 @@ resource "coder_app" "file_manager" {
|
||||
icon = "/icon/folder.svg"
|
||||
command = "bash -c 'export TERM=xterm-256color && cd /workspaces && ranger'"
|
||||
order = 5
|
||||
}
|
||||
}
|
||||
|
||||
14
tf/main.tf
14
tf/main.tf
@@ -103,7 +103,7 @@ data "coder_parameter" "enable_cursor_support" {
|
||||
|
||||
data "coder_parameter" "enable_windsurf_support" {
|
||||
name = "enable_windsurf_support"
|
||||
display_name = "Enable Windsurf IDE Support"
|
||||
display_name = "Enable Windsurf IDE Support"
|
||||
description = "Install Windsurf IDE configuration and settings"
|
||||
type = "bool"
|
||||
default = "true"
|
||||
@@ -143,9 +143,11 @@ data "coder_parameter" "enable_pgadmin" {
|
||||
|
||||
# Local Variables
|
||||
locals {
|
||||
# Container and workspace naming
|
||||
# Container and workspace naming - use ID for immutability
|
||||
container_name = "coder-${data.coder_workspace_owner.me.name}-${lower(data.coder_workspace.me.name)}"
|
||||
workspace_id = data.coder_workspace.me.id
|
||||
# Use workspace ID for volume naming to prevent destruction on rename
|
||||
volume_suffix = substr(data.coder_workspace.me.id, 0, 8)
|
||||
|
||||
# Git configuration
|
||||
git_author_name = coalesce(data.coder_workspace_owner.me.full_name, data.coder_workspace_owner.me.name)
|
||||
@@ -175,9 +177,9 @@ locals {
|
||||
"RUST_VERSION" = "stable"
|
||||
|
||||
# Service URLs (when services are enabled)
|
||||
"POSTGRES_URL" = data.coder_parameter.enable_services.value ? "postgresql://postgres:${var.postgres_password}@postgres-${local.workspace_id}:5432/postgres" : ""
|
||||
"REDIS_URL" = data.coder_parameter.enable_services.value ? "redis://:${var.redis_password}@redis-${local.workspace_id}:6379" : ""
|
||||
"QDRANT_URL" = data.coder_parameter.enable_services.value ? "http://qdrant-${local.workspace_id}:6333" : ""
|
||||
"POSTGRES_URL" = data.coder_parameter.enable_services.value ? "postgresql://postgres:${var.postgres_password}@postgres-${local.workspace_id}:5432/postgres" : ""
|
||||
"REDIS_URL" = data.coder_parameter.enable_services.value ? "redis://:${var.redis_password}@redis-${local.workspace_id}:6379" : ""
|
||||
"QDRANT_URL" = data.coder_parameter.enable_services.value ? "http://qdrant-${local.workspace_id}:6333" : ""
|
||||
|
||||
# Development configuration
|
||||
"EDITOR" = "code"
|
||||
@@ -233,4 +235,4 @@ resource "docker_volume" "workspaces" {
|
||||
resource "docker_image" "devcontainer" {
|
||||
name = local.devcontainer_image
|
||||
keep_locally = true
|
||||
}
|
||||
}
|
||||
|
||||
109
tf/scripts.tf
109
tf/scripts.tf
@@ -14,7 +14,25 @@ resource "coder_script" "claude_code_setup" {
|
||||
icon = "/icon/ai.svg"
|
||||
run_on_start = true
|
||||
|
||||
script = "bash /home/coder/resources/tf/scripts/claude-install.sh"
|
||||
script = <<-EOT
|
||||
#!/bin/bash
|
||||
set -e
|
||||
echo "Installing Claude Code CLI..."
|
||||
|
||||
# Check if Claude is already installed
|
||||
if command -v claude &> /dev/null; then
|
||||
echo "Claude Code CLI is already installed"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Install Claude Code CLI
|
||||
curl -fsSL https://claude.ai/install.sh | sh || {
|
||||
echo "Warning: Claude Code CLI installation failed or not available"
|
||||
exit 0
|
||||
}
|
||||
|
||||
echo "Claude Code CLI installation complete"
|
||||
EOT
|
||||
}
|
||||
|
||||
# =============================================================================
|
||||
@@ -28,7 +46,28 @@ resource "coder_script" "cursor_setup" {
|
||||
icon = "/icon/code.svg"
|
||||
run_on_start = true
|
||||
|
||||
script = "bash /home/coder/resources/tf/scripts/cursor-setup.sh"
|
||||
script = <<-EOT
|
||||
#!/bin/bash
|
||||
set -e
|
||||
echo "Configuring Cursor IDE support..."
|
||||
|
||||
# Create Cursor configuration directory
|
||||
mkdir -p ~/.config/cursor
|
||||
|
||||
# Add Cursor-specific settings
|
||||
cat > ~/.config/cursor/settings.json <<'EOF'
|
||||
{
|
||||
"workspaceFolder": "/workspaces",
|
||||
"remote.SSH.defaultExtensions": [
|
||||
"ms-python.python",
|
||||
"esbenp.prettier-vscode",
|
||||
"dbaeumer.vscode-eslint"
|
||||
]
|
||||
}
|
||||
EOF
|
||||
|
||||
echo "Cursor IDE support configured"
|
||||
EOT
|
||||
}
|
||||
|
||||
# =============================================================================
|
||||
@@ -42,7 +81,24 @@ resource "coder_script" "windsurf_setup" {
|
||||
icon = "/icon/code.svg"
|
||||
run_on_start = true
|
||||
|
||||
script = "bash /home/coder/resources/tf/scripts/windsurf-setup.sh"
|
||||
script = <<-EOT
|
||||
#!/bin/bash
|
||||
set -e
|
||||
echo "Configuring Windsurf IDE support..."
|
||||
|
||||
# Create Windsurf configuration directory
|
||||
mkdir -p ~/.config/windsurf
|
||||
|
||||
# Add Windsurf-specific settings
|
||||
cat > ~/.config/windsurf/settings.json <<'EOF'
|
||||
{
|
||||
"workspaceFolder": "/workspaces",
|
||||
"codeium.enabled": true
|
||||
}
|
||||
EOF
|
||||
|
||||
echo "Windsurf IDE support configured"
|
||||
EOT
|
||||
}
|
||||
|
||||
# =============================================================================
|
||||
@@ -55,7 +111,26 @@ resource "coder_script" "dev_extensions" {
|
||||
icon = "/icon/tools.svg"
|
||||
run_on_start = true
|
||||
|
||||
script = "bash /home/coder/resources/tf/scripts/dev-tools.sh"
|
||||
script = <<-EOT
|
||||
#!/bin/bash
|
||||
set -e
|
||||
echo "Installing development tools and extensions..."
|
||||
|
||||
# Install VS Code extensions if code-server is available
|
||||
if command -v code-server &> /dev/null; then
|
||||
code-server --install-extension ms-python.python || true
|
||||
code-server --install-extension esbenp.prettier-vscode || true
|
||||
code-server --install-extension dbaeumer.vscode-eslint || true
|
||||
code-server --install-extension ms-azuretools.vscode-docker || true
|
||||
fi
|
||||
|
||||
# Install additional development tools
|
||||
if ! command -v ranger &> /dev/null; then
|
||||
sudo apt-get update && sudo apt-get install -y ranger || true
|
||||
fi
|
||||
|
||||
echo "Development tools installation complete"
|
||||
EOT
|
||||
}
|
||||
|
||||
# =============================================================================
|
||||
@@ -68,5 +143,27 @@ resource "coder_script" "git_hooks_setup" {
|
||||
icon = "/icon/git.svg"
|
||||
run_on_start = true
|
||||
|
||||
script = "bash /home/coder/resources/tf/scripts/git-hooks.sh"
|
||||
}
|
||||
script = <<-EOT
|
||||
#!/bin/bash
|
||||
set -e
|
||||
echo "Setting up Git hooks and configuration..."
|
||||
|
||||
# Configure git
|
||||
git config --global user.name "${local.git_author_name}"
|
||||
git config --global user.email "${local.git_author_email}"
|
||||
git config --global init.defaultBranch main
|
||||
|
||||
# Create git hooks directory
|
||||
mkdir -p ~/.git-hooks
|
||||
|
||||
# Add a simple pre-commit hook template
|
||||
cat > ~/.git-hooks/pre-commit <<'EOF'
|
||||
#!/bin/bash
|
||||
# Pre-commit hook
|
||||
echo "Running pre-commit checks..."
|
||||
EOF
|
||||
chmod +x ~/.git-hooks/pre-commit
|
||||
|
||||
echo "Git hooks setup complete"
|
||||
EOT
|
||||
}
|
||||
|
||||
@@ -28,6 +28,10 @@ resource "docker_container" "postgres" {
|
||||
image = "postgres:${var.postgres_version}-alpine"
|
||||
name = "postgres-${local.workspace_id}"
|
||||
|
||||
# Resource limits for better isolation
|
||||
memory = 2048 * 1024 * 1024 # 2GB
|
||||
cpu_shares = 512 # Medium priority
|
||||
|
||||
# PostgreSQL configuration
|
||||
env = [
|
||||
"POSTGRES_DB=postgres",
|
||||
@@ -49,12 +53,13 @@ resource "docker_container" "postgres" {
|
||||
container_path = "/var/lib/postgresql/data"
|
||||
}
|
||||
|
||||
# Health check
|
||||
# Health check with proper timing for database startup
|
||||
healthcheck {
|
||||
test = ["CMD-SHELL", "pg_isready -U postgres"]
|
||||
interval = "15s"
|
||||
timeout = "5s"
|
||||
retries = 5
|
||||
test = ["CMD-SHELL", "pg_isready -U postgres"]
|
||||
interval = "15s"
|
||||
timeout = "5s"
|
||||
retries = 5
|
||||
start_period = "30s" # Give PostgreSQL time to initialize
|
||||
}
|
||||
|
||||
restart = "unless-stopped"
|
||||
@@ -94,6 +99,10 @@ resource "docker_container" "redis" {
|
||||
image = "redis:${var.redis_version}-alpine"
|
||||
name = "redis-${local.workspace_id}"
|
||||
|
||||
# Resource limits for better isolation
|
||||
memory = 1024 * 1024 * 1024 # 1GB
|
||||
cpu_shares = 256 # Lower priority
|
||||
|
||||
# Redis configuration with authentication
|
||||
command = [
|
||||
"redis-server",
|
||||
@@ -114,12 +123,13 @@ resource "docker_container" "redis" {
|
||||
container_path = "/data"
|
||||
}
|
||||
|
||||
# Health check with authentication
|
||||
# Health check with authentication and proper timing
|
||||
healthcheck {
|
||||
test = ["CMD", "redis-cli", "-a", var.redis_password, "ping"]
|
||||
interval = "15s"
|
||||
timeout = "3s"
|
||||
retries = 5
|
||||
test = ["CMD", "redis-cli", "-a", var.redis_password, "ping"]
|
||||
interval = "15s"
|
||||
timeout = "3s"
|
||||
retries = 5
|
||||
start_period = "10s" # Redis starts quickly
|
||||
}
|
||||
|
||||
restart = "unless-stopped"
|
||||
@@ -159,10 +169,14 @@ resource "docker_container" "qdrant" {
|
||||
image = "qdrant/qdrant:${var.qdrant_version}"
|
||||
name = "qdrant-${local.workspace_id}"
|
||||
|
||||
# Resource limits for better isolation
|
||||
memory = 2048 * 1024 * 1024 # 2GB for vector operations
|
||||
cpu_shares = 512 # Medium priority
|
||||
|
||||
# Qdrant configuration
|
||||
env = [
|
||||
"QDRANT__SERVICE__HTTP_PORT=6333",
|
||||
"QDRANT__SERVICE__GRPC_PORT=6334",
|
||||
"QDRANT__SERVICE__GRPC_PORT=6334",
|
||||
"QDRANT__SERVICE__HOST=0.0.0.0",
|
||||
"QDRANT__LOG_LEVEL=INFO"
|
||||
]
|
||||
@@ -177,12 +191,13 @@ resource "docker_container" "qdrant" {
|
||||
container_path = "/qdrant/storage"
|
||||
}
|
||||
|
||||
# Health check using simple file existence check (Qdrant creates lock files when running)
|
||||
# Health check using Qdrant's HTTP endpoint with proper timing
|
||||
healthcheck {
|
||||
test = ["CMD-SHELL", "test -d /qdrant/storage && test -f /qdrant/qdrant || exit 1"]
|
||||
interval = "20s"
|
||||
timeout = "5s"
|
||||
retries = 5
|
||||
test = ["CMD-SHELL", "wget --no-verbose --tries=1 --spider http://localhost:6333/health || exit 1"]
|
||||
interval = "20s"
|
||||
timeout = "5s"
|
||||
retries = 5
|
||||
start_period = "40s" # Qdrant needs time to initialize storage
|
||||
}
|
||||
|
||||
restart = "unless-stopped"
|
||||
@@ -244,10 +259,10 @@ resource "docker_container" "pgadmin" {
|
||||
|
||||
# Health check for pgAdmin web interface
|
||||
healthcheck {
|
||||
test = ["CMD-SHELL", "curl -f http://localhost:80/misc/ping || wget --no-verbose --tries=1 --spider http://localhost:80/misc/ping || exit 1"]
|
||||
interval = "30s"
|
||||
timeout = "10s"
|
||||
retries = 3
|
||||
test = ["CMD-SHELL", "nc -z localhost 80 || exit 1"]
|
||||
interval = "30s"
|
||||
timeout = "10s"
|
||||
retries = 3
|
||||
start_period = "60s"
|
||||
}
|
||||
|
||||
@@ -325,4 +340,4 @@ resource "docker_container" "jupyter" {
|
||||
label = "coder.workspace_id"
|
||||
value = local.workspace_id
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -102,4 +102,4 @@ common_tags = {
|
||||
Environment = "development"
|
||||
ManagedBy = "terraform"
|
||||
Purpose = "remote-development"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -307,6 +307,24 @@ variable "enable_jupyter" {
|
||||
default = false
|
||||
}
|
||||
|
||||
variable "enable_docker_in_docker" {
|
||||
description = "Enable Docker-in-Docker by mounting the Docker socket (Consider using Sysbox for better security)"
|
||||
type = bool
|
||||
default = true
|
||||
}
|
||||
|
||||
variable "use_sysbox_runtime" {
|
||||
description = "Use Sysbox runtime for secure container isolation (requires Sysbox installed on host)"
|
||||
type = bool
|
||||
default = false
|
||||
}
|
||||
|
||||
variable "block_file_transfer" {
|
||||
description = "Block file transfer commands (scp, rsync, ftp, nc) to prevent data exfiltration"
|
||||
type = bool
|
||||
default = false
|
||||
}
|
||||
|
||||
# =============================================================================
|
||||
# Common Tags
|
||||
# =============================================================================
|
||||
@@ -319,4 +337,4 @@ variable "common_tags" {
|
||||
ManagedBy = "terraform"
|
||||
Purpose = "remote-development"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,17 +24,19 @@ resource "coder_agent" "main" {
|
||||
"HOME" = "/home/coder"
|
||||
"USER" = "coder"
|
||||
# Service URLs for development
|
||||
"POSTGRES_URL" = data.coder_parameter.enable_services.value ? "postgresql://postgres:${var.postgres_password}@postgres-${local.workspace_id}:5432/postgres" : ""
|
||||
"REDIS_URL" = data.coder_parameter.enable_services.value ? "redis://:${var.redis_password}@redis-${local.workspace_id}:6379" : ""
|
||||
"QDRANT_URL" = data.coder_parameter.enable_services.value ? "http://qdrant-${local.workspace_id}:6333" : ""
|
||||
"POSTGRES_URL" = data.coder_parameter.enable_services.value ? "postgresql://postgres:${var.postgres_password}@postgres-${local.workspace_id}:5432/postgres" : ""
|
||||
"REDIS_URL" = data.coder_parameter.enable_services.value ? "redis://:${var.redis_password}@redis-${local.workspace_id}:6379" : ""
|
||||
"QDRANT_URL" = data.coder_parameter.enable_services.value ? "http://qdrant-${local.workspace_id}:6333" : ""
|
||||
# Additional environment variables for scripts
|
||||
"ENABLE_SERVICES" = tostring(data.coder_parameter.enable_services.value)
|
||||
"ENABLE_SERVICES" = tostring(data.coder_parameter.enable_services.value)
|
||||
# Security: Block file transfer commands to prevent data exfiltration
|
||||
"CODER_AGENT_BLOCK_FILE_TRANSFER" = var.block_file_transfer ? "1" : ""
|
||||
}
|
||||
|
||||
# Reference bind-mounted startup script plus service port forwarding
|
||||
startup_script = <<-EOT
|
||||
bash /home/coder/resources/tf/scripts/workspace-setup.sh
|
||||
|
||||
|
||||
# Register JetBrains Gateway backend location if enabled
|
||||
if [ "${data.coder_parameter.enable_jetbrains.value}" = "true" ] && [ -d ~/JetBrains ]; then
|
||||
~/JetBrains/*/bin/remote-dev-server.sh registerBackendLocationForGateway 2>/dev/null || echo "JetBrains Gateway registration skipped"
|
||||
@@ -75,6 +77,27 @@ resource "coder_agent" "main" {
|
||||
}
|
||||
}
|
||||
|
||||
# =============================================================================
|
||||
# Persistent Home Volume for Development Container
|
||||
# =============================================================================
|
||||
|
||||
resource "docker_volume" "coder_home" {
|
||||
name = "coder-home-${local.workspace_id}"
|
||||
|
||||
labels {
|
||||
label = "coder.workspace_id"
|
||||
value = local.workspace_id
|
||||
}
|
||||
labels {
|
||||
label = "coder.owner"
|
||||
value = data.coder_workspace_owner.me.name
|
||||
}
|
||||
labels {
|
||||
label = "coder.type"
|
||||
value = "home-directory"
|
||||
}
|
||||
}
|
||||
|
||||
# =============================================================================
|
||||
# Main Development Container
|
||||
# =============================================================================
|
||||
@@ -109,7 +132,7 @@ resource "docker_container" "workspace" {
|
||||
host = "host.docker.internal"
|
||||
ip = "host-gateway"
|
||||
}
|
||||
|
||||
|
||||
# No port mappings needed - reverse proxy will handle routing
|
||||
# All services run within the isolated workspace network
|
||||
# Coder's port forwarding and apps will provide access via reverse proxy
|
||||
@@ -122,24 +145,20 @@ resource "docker_container" "workspace" {
|
||||
read_only = false
|
||||
}
|
||||
|
||||
# Mount the existing coder-home volume for user data persistence
|
||||
# Mount a dynamically created home volume for user data persistence
|
||||
volumes {
|
||||
container_path = "/home/coder"
|
||||
volume_name = "bwk8ckcok8o84cc0o4os4sso_coder-home"
|
||||
volume_name = docker_volume.coder_home.name
|
||||
read_only = false
|
||||
}
|
||||
|
||||
# Bind mount code-tools directory for live script updates
|
||||
volumes {
|
||||
host_path = "/home/trav/code-tools"
|
||||
container_path = "/home/coder/resources"
|
||||
read_only = true
|
||||
}
|
||||
|
||||
# Docker socket for Docker-in-Docker
|
||||
volumes {
|
||||
host_path = "/var/run/docker.sock"
|
||||
container_path = "/var/run/docker.sock"
|
||||
# Docker socket for Docker-in-Docker (optional)
|
||||
dynamic "volumes" {
|
||||
for_each = var.enable_docker_in_docker ? [1] : []
|
||||
content {
|
||||
host_path = "/var/run/docker.sock"
|
||||
container_path = "/var/run/docker.sock"
|
||||
}
|
||||
}
|
||||
|
||||
# Working directory
|
||||
@@ -166,6 +185,7 @@ resource "docker_container" "workspace" {
|
||||
depends_on = [
|
||||
docker_network.workspace,
|
||||
docker_volume.workspaces,
|
||||
docker_volume.coder_home,
|
||||
docker_image.devcontainer
|
||||
]
|
||||
}
|
||||
@@ -221,4 +241,4 @@ module "jetbrains_gateway" {
|
||||
version = "2025.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user