Skip to content

Commit 2bc2746

Browse files
committed
Add emacs-pod template
1 parent 96e6cee commit 2bc2746

File tree

3 files changed

+245
-0
lines changed

3 files changed

+245
-0
lines changed

Dockerfile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ RUN apt-get update && \
3838
sudo
3939
# Created a ppa for emacs + broadway&nativecomp (build/Dockerfile has some of the process documented)
4040
# We need a custom build to run against broadwayd
41+
# https://launchpad.net/~hippiehacker/+archive/ubuntu/emacs-broadway
4142
RUN add-apt-repository ppa:hippiehacker/emacs-broadway --yes && \
4243
DEBIAN_FRONTEND="noninteractive" apt-get install --yes emacs-snapshot emacs-snapshot-el
4344
# Use upstream stable git

templates/emacs-pod/README.md

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
---
2+
name: Develop in Kubernetes
3+
description: Get started with Kubernetes development.
4+
tags: [cloud, kubernetes]
5+
---
6+
7+
# Getting started
8+
9+
This template creates a pod running the `codercom/enterprise-base:ubuntu` image.
10+
11+
## RBAC
12+
13+
The Coder provisioner requires permission to administer pods to use this template. The template
14+
creates workspaces in a single Kubernetes namespace, using the `workspaces_namespace` parameter set
15+
while creating the template.
16+
17+
Create a role as follows and bind it to the user or service account that runs the coder host.
18+
19+
```yaml
20+
apiVersion: rbac.authorization.k8s.io/v1
21+
kind: Role
22+
metadata:
23+
name: coder
24+
rules:
25+
- apiGroups: [""]
26+
resources: ["pods"]
27+
verbs: ["*"]
28+
```
29+
30+
## Authentication
31+
32+
This template can authenticate using in-cluster authentication, or using a kubeconfig local to the
33+
Coder host. For additional authentication options, consult the [Kubernetes provider
34+
documentation](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs).
35+
36+
### kubeconfig on Coder host
37+
38+
If the Coder host has a local `~/.kube/config`, you can use this to authenticate
39+
with Coder. Make sure this is done with same user that's running the `coder` service.
40+
41+
To use this authentication, set the parameter `use_kubeconfig` to true.
42+
43+
### In-cluster authentication
44+
45+
If the Coder host runs in a Pod on the same Kubernetes cluster as you are creating workspaces in,
46+
you can use in-cluster authentication.
47+
48+
To use this authentication, set the parameter `use_kubeconfig` to false.
49+
50+
The Terraform provisioner will automatically use the service account associated with the pod to
51+
authenticate to Kubernetes. Be sure to bind a [role with appropriate permission](#rbac) to the
52+
service account. For example, assuming the Coder host runs in the same namespace as you intend
53+
to create workspaces:
54+
55+
```yaml
56+
apiVersion: v1
57+
kind: ServiceAccount
58+
metadata:
59+
name: coder
60+
61+
---
62+
apiVersion: rbac.authorization.k8s.io/v1
63+
kind: RoleBinding
64+
metadata:
65+
name: coder
66+
subjects:
67+
- kind: ServiceAccount
68+
name: coder
69+
roleRef:
70+
kind: Role
71+
name: coder
72+
apiGroup: rbac.authorization.k8s.io
73+
```
74+
75+
Then start the Coder host with `serviceAccountName: coder` in the pod spec.
76+
77+
## Namespace
78+
79+
The target namespace in which the pod will be deployed is defined via the `coder_workspace`
80+
variable. The namespace must exist prior to creating workspaces.
81+
82+
## Persistence
83+
84+
The `/home/coder` directory in this example is persisted via the attached PersistentVolumeClaim.
85+
Any data saved outside of this directory will be wiped when the workspace stops.
86+
87+
Since most binary installations and environment configurations live outside of
88+
the `/home` directory, we suggest including these in the `startup_script` argument
89+
of the `coder_agent` resource block, which will run each time the workspace starts up.
90+
91+
For example, when installing the `aws` CLI, the install script will place the
92+
`aws` binary in `/usr/local/bin/aws`. To ensure the `aws` CLI is persisted across
93+
workspace starts/stops, include the following code in the `coder_agent` resource
94+
block of your workspace template:
95+
96+
```terraform
97+
resource "coder_agent" "main" {
98+
startup_script = <<EOT
99+
#!/bin/bash
100+
101+
# install AWS CLI
102+
curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
103+
unzip awscliv2.zip
104+
sudo ./aws/install
105+
EOT
106+
}
107+
```
108+
109+
## code-server
110+
111+
`code-server` is installed via the `startup_script` argument in the `coder_agent`
112+
resource block. The `coder_app` resource is defined to access `code-server` through
113+
the dashboard UI over `localhost:13337`.

templates/emacs-pod/main.tf

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
terraform {
2+
required_providers {
3+
coder = {
4+
source = "coder/coder"
5+
version = "0.6.1"
6+
}
7+
kubernetes = {
8+
source = "hashicorp/kubernetes"
9+
version = "~> 2.12.1"
10+
}
11+
}
12+
}
13+
14+
variable "use_kubeconfig" {
15+
type = bool
16+
default = false
17+
sensitive = true
18+
description = <<-EOF
19+
Use host kubeconfig? (true/false)
20+
21+
Set this to false if the Coder host is itself running as a Pod on the same
22+
Kubernetes cluster as you are deploying workspaces to.
23+
24+
Set this to true if the Coder host is running outside the Kubernetes cluster
25+
for workspaces. A valid "~/.kube/config" must be present on the Coder host.
26+
EOF
27+
}
28+
29+
variable "namespace" {
30+
type = string
31+
sensitive = true
32+
description = "The namespace to create workspaces in (must exist prior to creating workspaces)"
33+
default = "coder"
34+
}
35+
36+
provider "kubernetes" {
37+
# Authenticate via ~/.kube/config or a Coder-specific ServiceAccount, depending on admin preferences
38+
config_path = var.use_kubeconfig == true ? "~/.kube/config" : null
39+
}
40+
41+
data "coder_workspace" "me" {}
42+
43+
resource "coder_agent" "main" {
44+
os = "linux"
45+
arch = "amd64"
46+
startup_script = <<EOT
47+
#!/bin/bash
48+
49+
# home folder currently contains .emacs.d and .doom.d
50+
# at some point later we'll move them to another folder
51+
sudo apt-get install -y tmux ttyd libwebsockets-evlib-uv
52+
# start broadwayd and emacs
53+
broadwayd :5 2>&1 | tee broadwayd.log &
54+
GDK_BACKEND=broadway BROADWAY_DISPLAY=:5 emacs 2>&1 | tee emacs.log &
55+
# start ttyd / tmux
56+
tmux new -d
57+
ttyd tmux at 2>&1 | tee ttyd.log &
58+
EOT
59+
}
60+
61+
# emacs-broadway
62+
resource "coder_app" "emacs-broadway" {
63+
subdomain = true
64+
share = "public"
65+
agent_id = coder_agent.main.id
66+
slug = "emacs-broadway"
67+
display_name = "Emacs on Broadway"
68+
icon = "/icon/folder.svg" # let's maybe get an emacs.svg somehow
69+
url = "http://localhost:8085" # port 8080 + BROADWAY_DISPLAY
70+
71+
# healthcheck {
72+
# # don't want to disconnect current session, but hopefully this will 200OK
73+
# url = "http://localhost:8085/"
74+
# interval = 3
75+
# threshold = 10
76+
# }
77+
}
78+
79+
# ttyd
80+
resource "coder_app" "ttyd" {
81+
subdomain = true
82+
share = "public"
83+
slug = "ttyd"
84+
display_name = "ttyd for tmux"
85+
icon = "/icon/folder.svg" # let's maybe get an emacs.svg somehow
86+
agent_id = coder_agent.main.id
87+
url = "http://localhost:7681" # 7681 is the default ttyd port
88+
89+
# healthcheck {
90+
# # don't want to disconnect current session, but hopefully this will 200OK
91+
# url = "http://localhost:7681/"
92+
# interval = 3
93+
# threshold = 10
94+
# }
95+
}
96+
97+
# tmux
98+
resource "coder_app" "tmux" {
99+
agent_id = coder_agent.main.id
100+
display_name = "tmux"
101+
slug = "tmux"
102+
icon = "/icon/folder.svg" # let's maybe get an emacs.svg somehow
103+
command = "tmux at"
104+
share = "public"
105+
}
106+
107+
resource "kubernetes_pod" "main" {
108+
count = data.coder_workspace.me.start_count
109+
metadata {
110+
name = "coder-${lower(data.coder_workspace.me.owner)}-${lower(data.coder_workspace.me.name)}"
111+
namespace = var.namespace
112+
}
113+
spec {
114+
security_context {
115+
run_as_user = "1000"
116+
fs_group = "1000"
117+
}
118+
container {
119+
name = "dev"
120+
image = "ghcr.io/ii/emacs-coder:latest"
121+
command = ["sh", "-c", coder_agent.main.init_script]
122+
security_context {
123+
run_as_user = "1000"
124+
}
125+
env {
126+
name = "CODER_AGENT_TOKEN"
127+
value = coder_agent.main.token
128+
}
129+
}
130+
}
131+
}

0 commit comments

Comments
 (0)