diff --git a/templates/kubernetes/homelab-workspace/config/filebrowser.yaml b/templates/kubernetes/homelab-workspace/config/filebrowser.yaml new file mode 100644 index 00000000..7021e90e --- /dev/null +++ b/templates/kubernetes/homelab-workspace/config/filebrowser.yaml @@ -0,0 +1,32 @@ +--- +server: + port: 8080 + baseURL: "/" + cacheDir: "/home/filebrowser/data/tmp" + logging: + - levels: "info|warning|error" + sources: + - path: "/srv" + +# Coder's owner-only application proxy is the authentication boundary. The +# sidecar has no Service and File Browser is not reachable outside the Pod. +auth: + methods: + noauth: true + +frontend: + name: "Workspace Files" + disableDefaultLinks: true + +userDefaults: + listing: + showHidden: true + account: + permissions: + admin: false + api: false + create: true + delete: true + download: true + modify: true + share: false diff --git a/templates/kubernetes/homelab-workspace/configmap.tf b/templates/kubernetes/homelab-workspace/configmap.tf index 7ff01ef1..80ad63f4 100644 --- a/templates/kubernetes/homelab-workspace/configmap.tf +++ b/templates/kubernetes/homelab-workspace/configmap.tf @@ -18,6 +18,8 @@ resource "kubernetes_config_map_v1" "workspace_scripts" { "script-start-services.sh" = file("${path.cwd}/scripts/script-start-services.sh") "supervisord.conf" = file("${path.cwd}/config/supervisord.conf") "script-vscode-server-gc.sh" = file("${path.cwd}/scripts/script-vscode-server-gc.sh") + "filebrowser-agent-init.sh" = coder_agent.filebrowser.init_script + "filebrowser.yaml" = file("${path.cwd}/config/filebrowser.yaml") "workspace-init.sh" = coder_agent.main.init_script } } diff --git a/templates/kubernetes/homelab-workspace/deployment.tf b/templates/kubernetes/homelab-workspace/deployment.tf index e90d3424..5d77f406 100644 --- a/templates/kubernetes/homelab-workspace/deployment.tf +++ b/templates/kubernetes/homelab-workspace/deployment.tf @@ -145,6 +145,84 @@ resource "kubernetes_deployment_v1" "deployment" { name = "tmp" } } + container { + name = "filebrowser" + command = ["/bin/sh", "/scripts/filebrowser-agent-init.sh"] + image = "gtstef/filebrowser:1.5.6-stable@sha256:7c5d7ac8ffda31294d278063cf9d2e04303b39e6dce1f4c691342240ca7703b8" + env { + name = "CODER_AGENT_TOKEN" + value = coder_agent.filebrowser.token + } + env { + name = "FILEBROWSER_CONFIG" + value = "/config/filebrowser.yaml" + } + env { + name = "HOME" + value = "/home/filebrowser/data" + } + env { + name = "USER" + # The image's filebrowser account uses /bin/true. The agent uses + # this account only to select a shell; the Pod still enforces the + # non-root UID below. + value = "root" + } + port { + container_port = 8080 + name = "filebrowser" + protocol = "TCP" + } + liveness_probe { + http_get { + path = "/health" + port = 8080 + scheme = "HTTP" + } + initial_delay_seconds = 15 + period_seconds = 30 + timeout_seconds = 3 + failure_threshold = 3 + } + resources { + requests = { + "cpu" = "25m" + "memory" = "128Mi" + } + limits = { + "memory" = "256Mi" + } + } + security_context { + allow_privilege_escalation = false + read_only_root_filesystem = false + privileged = false + run_as_user = 10001 + run_as_group = 10001 + run_as_non_root = true + } + volume_mount { + mount_path = "/srv" + name = "home" + sub_path = data.coder_workspace.me.name + } + volume_mount { + mount_path = "/scripts/filebrowser-agent-init.sh" + name = "coder-scripts" + sub_path = "filebrowser-agent-init.sh" + read_only = true + } + volume_mount { + mount_path = "/config/filebrowser.yaml" + name = "coder-scripts" + sub_path = "filebrowser.yaml" + read_only = true + } + volume_mount { + mount_path = "/home/filebrowser/data" + name = "filebrowser-data" + } + } enable_service_links = false hostname = local.sanitized_workspace_name node_selector = { @@ -172,6 +250,10 @@ resource "kubernetes_deployment_v1" "deployment" { default_mode = "0750" } } + volume { + name = "filebrowser-data" + empty_dir {} + } # /tmp is scratch space (agent/tool tempfiles, build caches, downloaded # archives) and needs to be fast - it cannot be the NFS-backed "home" # PVC, and it cannot be an empty_dir either, because empty_dir lives on diff --git a/templates/kubernetes/homelab-workspace/filebrowser.tf b/templates/kubernetes/homelab-workspace/filebrowser.tf new file mode 100644 index 00000000..14b87891 --- /dev/null +++ b/templates/kubernetes/homelab-workspace/filebrowser.tf @@ -0,0 +1,36 @@ +resource "coder_agent" "filebrowser" { + arch = "amd64" + os = "linux" + api_key_scope = "no_user_data" + order = 1 + startup_script = "cd /home/filebrowser && ./filebrowser >/tmp/filebrowser.log 2>&1 &" + startup_script_behavior = "non-blocking" + + display_apps { + port_forwarding_helper = false + ssh_helper = false + vscode = false + vscode_insiders = false + web_terminal = false + } +} + +resource "coder_app" "filebrowser" { + agent_id = coder_agent.filebrowser.id + slug = "files" + display_name = "Files" + icon = "/icon/folder.svg" + url = "http://localhost:8080" + share = "owner" + # File Browser emits root-relative URLs and expects its configured base path + # on inbound requests. Coder path apps strip that path before proxying, so an + # isolated app subdomain is the only mode that preserves both contracts. + subdomain = true + open_in = "tab" + + healthcheck { + url = "http://localhost:8080/health" + interval = 5 + threshold = 6 + } +}