summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorhc <hc@email.ch>2025-05-30 22:51:55 +0800
committerhc <hc@email.ch>2025-05-30 22:51:55 +0800
commit7b94af70555aab814f964a08098d0fb123171f7e (patch)
tree2b8cf5793a7ecee85122133b4a59cad824e0c912
dev_env
-rw-r--r--.claude/settings.local.json9
-rw-r--r--docker_build/Dockerfile50
-rw-r--r--docker_build/vimrc77
-rw-r--r--docs48
-rwxr-xr-xpodman_launch_devenv.py49
-rw-r--r--rocky-ssh-deployment.yaml48
-rw-r--r--ssh-keys/macm4-resident.pub1
7 files changed, 282 insertions, 0 deletions
diff --git a/.claude/settings.local.json b/.claude/settings.local.json
new file mode 100644
index 0000000..f689325
--- /dev/null
+++ b/.claude/settings.local.json
@@ -0,0 +1,9 @@
1{
2 "permissions": {
3 "allow": [
4 "Bash(rm:*)",
5 "Bash(chmod:*)"
6 ],
7 "deny": []
8 }
9} \ No newline at end of file
diff --git a/docker_build/Dockerfile b/docker_build/Dockerfile
new file mode 100644
index 0000000..644b18f
--- /dev/null
+++ b/docker_build/Dockerfile
@@ -0,0 +1,50 @@
1FROM rockylinux:9
2
3# Install required packages, resolving curl conflict
4RUN dnf install -y epel-release
5RUN dnf install -y --allowerasing openssh-server sudo procps-ng \
6 gcc gcc-c++ make cmake pkg-config openssl-devel libicu-devel perl python3-devel \
7 nc openssl bat autossh tmux htop tar bmon gzip tree wget \
8 nano vim unzip net-tools git python3 python3-pip make wireguard-tools usbutils yum xclip \
9 && dnf clean all
10
11# Configure SSH
12RUN mkdir -p /var/run/sshd && \
13 ssh-keygen -A && \
14 sed -i 's/#PubkeyAuthentication yes/PubkeyAuthentication yes/' /etc/ssh/sshd_config && \
15 sed -i 's/#PermitRootLogin prohibit-password/PermitRootLogin yes/' /etc/ssh/sshd_config && \
16 sed -i 's/#PasswordAuthentication yes/PasswordAuthentication no/' /etc/ssh/sshd_config
17
18# Setup SSH directory for root and ensure root has valid shell
19RUN mkdir -p /root/.ssh && \
20 chmod 700 /root/.ssh && \
21 usermod -s /bin/bash root
22
23# Copy SSH public keys from ssh-keys directory into the image
24COPY ssh-keys/*.pub /tmp/ssh-keys/
25RUN cat /tmp/ssh-keys/*.pub > /root/.ssh/authorized_keys && \
26 chmod 600 /root/.ssh/authorized_keys && \
27 rm -rf /tmp/ssh-keys
28
29# Configure vim
30COPY docker_build/vimrc /etc/vimrc
31
32# Configure bash prompt and colors
33RUN echo 'LS_COLORS=$LS_COLORS:"di=38;5;135:ex=00;32:" ; export LS_COLORS' >> /etc/bashrc && \
34 echo 'PS1="[\[\033[01;32m\]\u\[\033[00m\]@\h \[\033[38;5;135m\]\W\[\033[00m\]]\$ "' >> /etc/bashrc && \
35 echo 'export PATH=$PATH:/root/.cargo/bin' >> /root/.bashrc
36
37# Install Rust and tools for root
38RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y && \
39 echo '[ -f "$HOME/.cargo/env" ] && source "$HOME/.cargo/env"' >> ~/.bashrc && \
40 source "$HOME/.cargo/env" && \
41 cargo install cargo-clone-crate cargo-edit cargo-info evcxr_jupyter bacon du-dust
42
43# Set working directory
44WORKDIR /root
45
46# Expose SSH port
47EXPOSE 22
48
49# Start SSH daemon
50CMD ["/usr/sbin/sshd", "-D", "-e"] \ No newline at end of file
diff --git a/docker_build/vimrc b/docker_build/vimrc
new file mode 100644
index 0000000..36583bc
--- /dev/null
+++ b/docker_build/vimrc
@@ -0,0 +1,77 @@
1" Basic vim configuration for development environment
2
3" Enable syntax highlighting
4syntax on
5
6" Enable line numbers
7set number
8
9" Enable relative line numbers for easier navigation
10set relativenumber
11
12" Set tab width to 4 spaces
13set tabstop=4
14set shiftwidth=4
15set expandtab
16
17" Enable auto-indentation
18set autoindent
19set smartindent
20
21" Enable incremental search
22set incsearch
23
24" Highlight search results
25set hlsearch
26
27" Case-insensitive search unless uppercase is used
28set ignorecase
29set smartcase
30
31" Show matching brackets
32set showmatch
33
34" Enable mouse support
35set mouse=a
36
37" Set backspace behavior
38set backspace=indent,eol,start
39
40" Show current line and column
41set ruler
42
43" Enable file type detection
44filetype on
45filetype plugin on
46filetype indent on
47
48" Set color scheme (if available)
49colorscheme default
50
51" Enable visual bell instead of beep
52set visualbell
53
54" Set encoding
55set encoding=utf-8
56
57" Show command in status line
58set showcmd
59
60" Enable wildmenu for command completion
61set wildmenu
62
63" Set status line
64set laststatus=2
65set statusline=%F%m%r%h%w\ [%l,%c]\ [%L\ lines]
66
67" Rust specific settings
68autocmd FileType rust setlocal tabstop=4 shiftwidth=4 expandtab
69
70" Python specific settings
71autocmd FileType python setlocal tabstop=4 shiftwidth=4 expandtab
72
73" JavaScript/TypeScript settings
74autocmd FileType javascript,typescript setlocal tabstop=2 shiftwidth=2 expandtab
75
76" YAML settings
77autocmd FileType yaml setlocal tabstop=2 shiftwidth=2 expandtab \ No newline at end of file
diff --git a/docs b/docs
new file mode 100644
index 0000000..50aca64
--- /dev/null
+++ b/docs
@@ -0,0 +1,48 @@
1# Rocky SSH Container
2Rocky Linux development environment with SSH access for Podman and Kubernetes.
3
4## Launcher Commands
5```bash
6# Check image status and show build commands
7python3 launcher.py
8python3 launcher.py run
9python3 launcher.py run -p 2222
10python3 launcher.py list
11python3 launcher.py cleanup
12```
13
14## Kubernetes Commands
15```bash
16kubectl apply -f rocky-ssh-deployment.yaml
17# Check pods with IPs
18kubectl get pods -l app=rocky-dev-deploy -o wide
19# Check services (networking), get deployment is for stateless (not this)
20kubectl get svc rocky-dev-deploy-svc
21# Delete specific pod (auto-recreates)
22kubectl delete pod rocky-dev-deploy-0
23# Scale replicas
24kubectl scale statefulset rocky-dev-deploy --replicas=10
25kubectl delete -f rocky-ssh-deployment.yaml
26```
27
28## Local Registry (for Kubernetes)
29```bash
30# Run a local registry
31podman run -d -p 5000:5000 --name registry registry:2
32# Tag and push to local registry
33podman tag localhost/rocky_dev:latest localhost:5000/rocky_dev:latest
34podman push localhost:5000/rocky_dev:latest --tls-verify=false
35# Update image in rocky-ssh-deployment.yaml to: localhost:5000/rocky_dev:latest
36```
37
38## SSH Access
39```bash
40# Podman (launcher shows connection command)
41ssh root@<host> -p <port>
42# Kubernetes (port forward - localhost only)
43kubectl port-forward <pod-name> 2222:22
44ssh root@localhost -p 2222
45# Kubernetes (port forward - external access)
46kubectl port-forward --address 0.0.0.0 <pod-name> 9999:22
47ssh root@<host> -p 9999
48```
diff --git a/podman_launch_devenv.py b/podman_launch_devenv.py
new file mode 100755
index 0000000..a155b8f
--- /dev/null
+++ b/podman_launch_devenv.py
@@ -0,0 +1,49 @@
1#!/usr/bin/env python3
2"""
3Rocky SSH Container Launcher
4
5Manual build command:
6 podman build -f docker-build/Dockerfile -t rocky_dev:latest .
7
8Usage:
9 python3 launcher.py # Build and launch container
10 python3 launcher.py --list # List running rocky-dev containers
11 python3 launcher.py --cleanup # Stop and remove all containers
12"""
13import subprocess, argparse, os, glob
14
15def run(cmd): return subprocess.run(cmd, shell=True, capture_output=True, text=True)
16
17def build():
18 if not glob.glob("ssh-keys/*.pub"): os.makedirs("ssh-keys", exist_ok=True); open("ssh-keys/dummy.pub", "w").write("# dummy")
19 result = run("podman build -f docker_build/Dockerfile -t rocky_dev:latest .")
20 if os.path.exists("ssh-keys/dummy.pub"): os.remove("ssh-keys/dummy.pub")
21 return result.returncode == 0
22
23def launch():
24 port = str(args.port) if args.port else run("shuf -i 10000-65000 -n 1").stdout.strip()
25 result = run(f"podman run -d -p {port}:22 --privileged --name rocky_dev-{port} rocky_dev:latest")
26 if result.returncode == 0:
27 ip = run("hostname -I | awk '{print $1}'").stdout.strip() or "localhost"
28 print(f"🐳 SSH: ssh root@{ip} -p {port}")
29 return result.returncode == 0
30
31parser = argparse.ArgumentParser(epilog="""
32Manual build commands:
33 Build: podman build -f docker_build/Dockerfile -t rocky_dev:latest .
34 Rebuild: podman rmi rocky_dev:latest && podman build -f docker_build/Dockerfile -t rocky_dev:latest .
35""", formatter_class=argparse.RawDescriptionHelpFormatter)
36parser.add_argument("command", nargs="?", choices=["run", "list", "cleanup"], help="Command to execute")
37parser.add_argument("-p", "--port", type=int)
38args = parser.parse_args()
39
40if args.command == "list": print(run("podman ps --filter name=rocky_dev").stdout or "No containers")
41elif args.command == "cleanup": [run(f"podman stop {c} && podman rm {c}") for c in run("podman ps -a --filter name=rocky_dev --format '{{.Names}}'").stdout.split()]
42elif args.command == "run":
43 if run("podman images -q rocky_dev").stdout:
44 print("found rocky_dev container! starting with a random public port to ssh... ")
45 launch()
46 else:
47 print("❌ Image rocky_dev:latest not found")
48else:
49 print("Usage: python3 launcher.py {run|list|cleanup} [-p PORT]")
diff --git a/rocky-ssh-deployment.yaml b/rocky-ssh-deployment.yaml
new file mode 100644
index 0000000..61e0dc9
--- /dev/null
+++ b/rocky-ssh-deployment.yaml
@@ -0,0 +1,48 @@
1apiVersion: apps/v1
2kind: StatefulSet
3metadata:
4 name: rocky-dev-deploy
5 labels:
6 app: rocky-dev-deploy
7spec:
8 serviceName: rocky-dev-deploy-svc
9 replicas: 3
10 selector:
11 matchLabels:
12 app: rocky-dev-deploy
13 template:
14 metadata:
15 labels:
16 app: rocky-dev-deploy
17 spec:
18 containers:
19 - name: rocky-dev-deploy
20 image: localhost:5000/rocky_dev:latest
21 imagePullPolicy: IfNotPresent # Use local image
22 ports:
23 - containerPort: 22
24 name: ssh
25 securityContext:
26 privileged: true
27 livenessProbe:
28 tcpSocket:
29 port: 22
30 initialDelaySeconds: 30
31 periodSeconds: 30
32 readinessProbe:
33 tcpSocket:
34 port: 22
35 initialDelaySeconds: 5
36 periodSeconds: 10
37---
38apiVersion: v1
39kind: Service
40metadata:
41 name: rocky-dev-deploy-svc
42spec:
43 clusterIP: None
44 selector:
45 app: rocky-dev-deploy
46 ports:
47 - port: 22
48 targetPort: 22
diff --git a/ssh-keys/macm4-resident.pub b/ssh-keys/macm4-resident.pub
new file mode 100644
index 0000000..fbccb4f
--- /dev/null
+++ b/ssh-keys/macm4-resident.pub
@@ -0,0 +1 @@
sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAIFdHP8n64jOV6Ok7U9TDnGW+LUkXP6V7cvXH6xqN0zcNAAAAEnNzaDptYWNtNC1yZXNpZGVudA== ssh:macm4-resident