From 2d16e730869cfc533789b57c12e54578969d8a1b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?William=20S=C3=B6derberg?= Date: Fri, 17 Oct 2025 23:33:14 +0200 Subject: [PATCH] First Commit --- .github/workflows/publish-template.yaml | 60 ++++++++ README.md | 20 +++ build/Dockerfile | 31 ++++ main.tf | 188 ++++++++++++++++++++++++ 4 files changed, 299 insertions(+) create mode 100644 .github/workflows/publish-template.yaml create mode 100644 README.md create mode 100644 build/Dockerfile create mode 100644 main.tf diff --git a/.github/workflows/publish-template.yaml b/.github/workflows/publish-template.yaml new file mode 100644 index 0000000..2a2661c --- /dev/null +++ b/.github/workflows/publish-template.yaml @@ -0,0 +1,60 @@ +name: Test and Publish Coder Template + +on: + push: + branches: + - main + workflow_dispatch: + +jobs: + test-and-publish: + runs-on: ubuntu-latest + env: + TEMPLATE_NAME: "LaTeX" + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Set up Terraform + uses: hashicorp/setup-terraform@v2 + with: + terraform_version: latest + + - name: Set up Coder CLI + uses: coder/setup-action@v1 + with: + access_url: "https://coder.soderberg.tech" + coder_session_token: ${{ secrets.CODER_SESSION_TOKEN }} + + - name: Initilize Terraform + run: terraform init + + - name: Validate Terraform template + run: terraform validate + + - name: Get short commit SHA to use as template version name + id: name + run: echo "version_name=$(git rev-parse --short HEAD)" >> "$GITHUB_OUTPUT" + + - name: Get latest commit title to use as template version description + id: message + run: + echo "pr_title=$(git log --format=%s -n 1 ${{ github.sha }})" >> + $GITHUB_OUTPUT + + - name: Push template to Coder + run: | + coder templates push $TEMPLATE_NAME -d $GITHUB_WORKSPACE --activate=false --name ${{ steps.name.outputs.version_name }} --message "${{ steps.message.outputs.pr_title }}" --yes + + - name: Create a test workspace + run: | + coder create -t $TEMPLATE_NAME --template-version ${{ steps.name.outputs.version_name }} test-${{ steps.name.outputs.version_name }} --yes --parameter "username=TEST-GIT-NAME" + + - name: Delete the test workspace + if: always() + run: coder delete test-${{ steps.name.outputs.version_name }} --yes + + - name: Promote template version + if: success() + run: | + coder template version promote --template=$TEMPLATE_NAME --template-version=${{ steps.name.outputs.version_name }} diff --git a/README.md b/README.md new file mode 100644 index 0000000..238bf4b --- /dev/null +++ b/README.md @@ -0,0 +1,20 @@ +# LTH Docker + +## Configure X11 capabilities + +1. Install a X Server on your device, [X410](https://x410.dev/) is recommended. + +2. Open VS Code and add two entries to the ***coder.sshConfig*** setting (restart VS Code afterwards): + - `ForwardX11 yes` + - `ForwardX11Trusted yes` + +> You might need to input the following into a terminal on Windows: `setx DISPLAY "127.0.0.1:0.0"` if the X11 display can't be found. + +## Architecture + +This template provisions the following resources: + +- Docker image (built by Docker socket and kept locally) +- Docker volume (persistent on `/home/{User}`) + +This means, when the workspace restarts, any tools or files outside of the home directory are not persisted. diff --git a/build/Dockerfile b/build/Dockerfile new file mode 100644 index 0000000..088eece --- /dev/null +++ b/build/Dockerfile @@ -0,0 +1,31 @@ +FROM ubuntu:latest + +# Updates and installs commons +RUN apt-get update \ + && apt-get install -y \ + curl \ + git \ + sudo \ + vim \ + wget \ + locales + +# Sets local +RUN localedef -i en_US -c -f UTF-8 -A /usr/share/locale/locale.alias en_US.UTF-8 +ENV LANG=en_US.utf8 + +# Install LaTeX +RUN apt-get install -y texlive-full + +# Clears apt lists +RUN rm -rf /var/lib/apt/lists/* + +# Adds the default User +ARG USER=lth-student +RUN useradd --groups sudo --no-create-home --shell /bin/bash ${USER} \ + && echo "${USER} ALL=(ALL) NOPASSWD:ALL" >/etc/sudoers.d/${USER} \ + && chmod 0440 /etc/sudoers.d/${USER} + +# Sets user and work directory +USER ${USER} +WORKDIR /home/${USER} \ No newline at end of file diff --git a/main.tf b/main.tf new file mode 100644 index 0000000..484ea75 --- /dev/null +++ b/main.tf @@ -0,0 +1,188 @@ +terraform { + required_providers { + coder = { + source = "coder/coder" + } + docker = { + source = "kreuzwerker/docker" + } + } +} + +provider "docker" {} + +data "coder_provisioner" "me" {} + +data "coder_workspace" "me" {} + +data "coder_workspace_owner" "me" {} + +locals { + username = data.coder_workspace_owner.me.name + docker_name = lower("coder-${data.coder_workspace.me.template_name}-${local.username}-${data.coder_workspace.me.id}") +} + +resource "coder_agent" "main" { + arch = data.coder_provisioner.me.arch + os = "linux" + startup_script = <<-EOT + set -e + + # Prepare user home with default files on first start. + if [ ! -f ~/.init_done ]; then + cp -rT /etc/skel ~ + touch ~/.init_done + fi + + EOT + + # These environment variables allow you to make Git commits right away after creating a + # workspace. Note that they take precedence over configuration defined in ~/.gitconfig! + # You can remove this block if you'd prefer to configure Git manually or using + # dotfiles. (see docs/dotfiles.md) + env = { + GIT_AUTHOR_NAME = coalesce(data.coder_workspace_owner.me.full_name, data.coder_workspace_owner.me.name) + GIT_AUTHOR_EMAIL = "${data.coder_workspace_owner.me.email}" + GIT_COMMITTER_NAME = coalesce(data.coder_workspace_owner.me.full_name, data.coder_workspace_owner.me.name) + GIT_COMMITTER_EMAIL = "${data.coder_workspace_owner.me.email}" + } + + # The following metadata blocks are optional. They are used to display + # information about your workspace in the dashboard. You can remove them + # if you don't want to display any information. + # For basic resources, you can use the `coder stat` command. + # If you need more control, you can write your own script. + metadata { + display_name = "CPU Usage" + key = "0_cpu_usage" + script = "coder stat cpu" + interval = 10 + timeout = 1 + } + + metadata { + display_name = "RAM Usage" + key = "1_ram_usage" + script = "coder stat mem" + interval = 10 + timeout = 1 + } + + metadata { + display_name = "Home Disk" + key = "3_home_disk" + script = "coder stat disk --path $${HOME}" + interval = 60 + timeout = 1 + } + +} + +module "vscode-web" { + count = data.coder_workspace.me.start_count + source = "registry.coder.com/coder/vscode-web/coder" + version = "1.4.1" + agent_id = coder_agent.main.id + folder = "/home/${local.username}" + accept_license = true + extensions = [ + "James-Yu.latex-workshop", + "tomoki1207.pdf" + ] + settings = { + "workbench.startupEditor": "none", + "workbench.colorTheme": "Default Dark Modern", + "window.menuBarVisibility": "classic", + "files.exclude": { + ".*/": true + } + } +} + +module "git-config" { + count = data.coder_workspace.me.start_count + source = "registry.coder.com/coder/git-config/coder" + version = "1.0.31" + agent_id = coder_agent.main.id +} + +resource "docker_volume" "home_volume" { + name = local.docker_name + # Protect the volume from being deleted due to changes in attributes. + lifecycle { + ignore_changes = all + } + # Add labels in Docker to keep track of orphan resources. + labels { + label = "coder.owner" + value = data.coder_workspace_owner.me.name + } + labels { + label = "coder.owner_id" + value = data.coder_workspace_owner.me.id + } + labels { + label = "coder.workspace_id" + value = data.coder_workspace.me.id + } + # This field becomes outdated if the workspace is renamed but can + # be useful for debugging or cleaning out dangling volumes. + labels { + label = "coder.workspace_name_at_creation" + value = data.coder_workspace.me.name + } +} + +resource "docker_image" "main" { + name = local.docker_name + build { + context = "./build" + build_args = { + USER = local.username + } + } + triggers = { + dir_sha1 = sha1(join("", [for f in fileset(path.module, "build/*") : filesha1(f)])) + } +} + +resource "docker_container" "workspace" { + count = data.coder_workspace.me.start_count + image = docker_image.main.name + cpu_set = "0-11" + memory = 4096 + # Uses lower() to avoid Docker restriction on container names. + name = "coder-${data.coder_workspace_owner.me.name}-${lower(data.coder_workspace.me.name)}" + # Hostname makes the shell more user friendly: coder@my-workspace:~$ + hostname = data.coder_workspace.me.name + # Use the docker gateway if the access URL is 127.0.0.1 + entrypoint = ["sh", "-c", replace(coder_agent.main.init_script, "/localhost|127\\.0\\.0\\.1/", "host.docker.internal")] + env = ["CODER_AGENT_TOKEN=${coder_agent.main.token}"] + host { + host = "host.docker.internal" + ip = "host-gateway" + } + volumes { + container_path = "/home/${local.username}" + volume_name = docker_volume.home_volume.name + read_only = false + } + + # Add labels in Docker to keep track of orphan resources. + labels { + label = "coder.owner" + value = data.coder_workspace_owner.me.name + } + labels { + label = "coder.owner_id" + value = data.coder_workspace_owner.me.id + } + labels { + label = "coder.workspace_id" + value = data.coder_workspace.me.id + } + labels { + label = "coder.workspace_name" + value = data.coder_workspace.me.name + } +}