mirror of
https://github.com/sailor-sh/CK-X.git
synced 2026-02-19 20:09:51 +00:00
Compare commits
22 Commits
feat/clust
...
feature/v2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ed3832e517 | ||
|
|
77e226df15 | ||
|
|
2284a1b72f | ||
|
|
eaa11c1ad0 | ||
|
|
038e9de8c2 | ||
|
|
eb2eb1e047 | ||
|
|
dd436c0d2c | ||
|
|
d54d35f53e | ||
|
|
9ccb20e287 | ||
|
|
95c771ff9e | ||
|
|
7e1b32a3d9 | ||
|
|
502ee9f4de | ||
|
|
c308a4d455 | ||
|
|
9c3777931a | ||
|
|
6f42a6991a | ||
|
|
e72959ebee | ||
|
|
328fe6a1f4 | ||
|
|
256d782722 | ||
|
|
8c31da5e6e | ||
|
|
df9e9d33c4 | ||
|
|
d052945bfe | ||
|
|
ecd285e683 |
@@ -12,7 +12,7 @@ A powerful Kubernetes certification practice environment that provides a realist
|
||||
- Comprehensive practice labs for **CKAD, CKA, CKS**, and other Kubernetes certifications
|
||||
- **Smart evaluation system** with real-time solution verification
|
||||
- **Docker-based deployment** for easy setup and consistent environment
|
||||
- **Timed exam mode** with real exam-like conditions and countdown timer
|
||||
- **Timed exam mode** with real exam-like conditions and countdown timer
|
||||
|
||||
|
||||
##
|
||||
@@ -38,7 +38,7 @@ For detailed installation instructions, please refer to our [Deployment Guide](s
|
||||
|
||||
## Community & Support
|
||||
|
||||
- Join our [Telegram Community](https://t.me/ckxdev) for discussions and support
|
||||
- Join our [Discord Community](https://discord.gg/6FPQMXNgG9) for discussions and support
|
||||
- Feature requests and pull requests are welcome
|
||||
|
||||
## Adding New Labs
|
||||
|
||||
@@ -60,6 +60,5 @@
|
||||
// Set the current year for copyright
|
||||
document.getElementById('currentYear').textContent = new Date().getFullYear();
|
||||
</script>
|
||||
<script data-name="BMC-Widget" data-cfasync="false" src="https://cdnjs.buymeacoffee.com/1.0.0/widget.prod.min.js" data-id="nishan.b" data-description="Support me on Buy me a coffee!" data-message="CK-X helped you prep? A coffee helps it grow !!" data-color="#5F7FFF" data-position="Right" data-x_margin="18" data-y_margin="18"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -4,7 +4,7 @@
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta name="mobile-web-app-capable" content="yes">
|
||||
<title>CK-X | Kubernetes Certification Simulator</title>
|
||||
<title>CK-X Cloud | Kubernetes Certification Simulator</title>
|
||||
<!-- Bootstrap CSS -->
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||
<!-- Font Awesome -->
|
||||
@@ -24,7 +24,7 @@
|
||||
<!-- Navbar -->
|
||||
<nav class="navbar navbar-expand-lg navbar-dark bg-dark fixed-top">
|
||||
<div class="container">
|
||||
<a class="navbar-brand" href="/">CK-X</a>
|
||||
<a class="navbar-brand" href="/">CK-X Cloud</a>
|
||||
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
@@ -40,14 +40,6 @@
|
||||
View Result
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="https://github.com/nishanb/ck-x" target="_blank">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor" class="bi bi-github" viewBox="0 0 16 16">
|
||||
<path d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.012 8.012 0 0 0 16 8c0-4.42-3.58-8-8-8z"/>
|
||||
</svg>
|
||||
GitHub
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
@@ -232,12 +224,10 @@
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script>
|
||||
<!-- Custom JS -->
|
||||
<script src="/js/index.js"></script>
|
||||
<!-- Buy Me a Coffee Widget -->
|
||||
<script data-name="BMC-Widget" data-cfasync="false" src="https://cdnjs.buymeacoffee.com/1.0.0/widget.prod.min.js" data-id="nishan.b" data-description="Support me on Buy me a coffee!" data-message="" data-color="#5F7FFF" data-position="Right" data-x_margin="18" data-y_margin="18"></script>
|
||||
|
||||
<!-- Footer -->
|
||||
<footer class="text-center py-4 mt-4">
|
||||
<p>Made with <span style="color: #ff3366;">❤️</span> | <a href="https://ckx.nishann.com" target="_blank">ckx.nishann.com</a></p>
|
||||
<p>Made with <span style="color: #ff3366;">❤️</span> | <a href="https://play.sailor.sh" target="_blank">sailor.sh</a></p>
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
||||
@@ -17,7 +17,6 @@ const feedbackState = {
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
// DOM elements
|
||||
const feedbackModal = document.getElementById('feedbackModal');
|
||||
const skipFeedbackBtn = document.getElementById('skipFeedbackBtn');
|
||||
const submitFeedbackBtn = document.getElementById('submitFeedbackBtn');
|
||||
const testimonialConsent = document.getElementById('testimonialConsent');
|
||||
const testimonialFields = document.getElementById('testimonialFields');
|
||||
@@ -66,16 +65,6 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
feedbackState.socialHandle = this.value.trim();
|
||||
});
|
||||
|
||||
// Skip feedback handler
|
||||
skipFeedbackBtn.addEventListener('click', function() {
|
||||
// Set a timestamp for when to ask again (30 minutes from now)
|
||||
const thirtyMinutesFromNow = new Date().getTime() + (30 * 60 * 1000);
|
||||
localStorage.setItem('ckx_feedback_skip_until', thirtyMinutesFromNow);
|
||||
|
||||
// Hide the modal
|
||||
feedbackModal.style.display = 'none';
|
||||
});
|
||||
|
||||
// Submit feedback handler
|
||||
submitFeedbackBtn.addEventListener('click', function() {
|
||||
// Validate that we have at least a rating
|
||||
|
||||
@@ -159,13 +159,11 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button id="skipFeedbackBtn" class="btn btn-secondary">Skip for now</button>
|
||||
<button id="submitFeedbackBtn" class="btn btn-primary">
|
||||
<i class="fas fa-paper-plane me-2"></i> Submit Feedback
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script data-name="BMC-Widget" data-cfasync="false" src="https://cdnjs.buymeacoffee.com/1.0.0/widget.prod.min.js" data-id="nishan.b" data-description="Support me on Buy me a coffee!" data-message="CK-X helped you prep? A coffee helps it grow !!" data-color="#5F7FFF" data-position="Right" data-x_margin="18" data-y_margin="18"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -6,8 +6,8 @@ services:
|
||||
context: ./remote-desktop
|
||||
hostname: terminal
|
||||
expose:
|
||||
- "5901" # VNC port (internal only)
|
||||
- "6901" # Web VNC port (internal only)
|
||||
- "5901" # VNC port (internal only)
|
||||
- "6901" # Web VNC port (internal only)
|
||||
environment:
|
||||
- VNC_PW=bakku-the-wizard
|
||||
- VNC_PASSWORD=bakku-the-wizard
|
||||
@@ -21,10 +21,10 @@ services:
|
||||
deploy:
|
||||
resources:
|
||||
limits:
|
||||
cpus: '1'
|
||||
cpus: "1"
|
||||
memory: 1G
|
||||
reservations:
|
||||
cpus: '0.5'
|
||||
cpus: "0.5"
|
||||
memory: 512M
|
||||
networks:
|
||||
- ckx-network
|
||||
@@ -35,7 +35,7 @@ services:
|
||||
build:
|
||||
context: ./app
|
||||
expose:
|
||||
- "3000" # Only exposed to internal network
|
||||
- "3000" # Only exposed to internal network
|
||||
environment:
|
||||
- VNC_SERVICE_HOST=remote-desktop
|
||||
- VNC_SERVICE_PORT=6901
|
||||
@@ -47,10 +47,10 @@ services:
|
||||
deploy:
|
||||
resources:
|
||||
limits:
|
||||
cpus: '0.5'
|
||||
cpus: "0.5"
|
||||
memory: 512M
|
||||
reservations:
|
||||
cpus: '0.2'
|
||||
cpus: "0.2"
|
||||
memory: 256M
|
||||
healthcheck:
|
||||
test: ["CMD", "wget", "-q", "-O", "-", "http://localhost:3000/"]
|
||||
@@ -72,14 +72,14 @@ services:
|
||||
- facilitator
|
||||
- k8s-api-server
|
||||
ports:
|
||||
- "30080:80" # Expose Nginx on port 30080
|
||||
- "30080:80" # Expose Nginx on port 30080
|
||||
deploy:
|
||||
resources:
|
||||
limits:
|
||||
cpus: '0.2'
|
||||
cpus: "0.2"
|
||||
memory: 256M
|
||||
reservations:
|
||||
cpus: '0.1'
|
||||
cpus: "0.1"
|
||||
memory: 128M
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "-f", "http://localhost/"]
|
||||
@@ -98,15 +98,15 @@ services:
|
||||
privileged: true
|
||||
# No external port mappings - only accessible internally
|
||||
expose:
|
||||
- "22" # SSH port (internal only)
|
||||
- "22" # SSH port (internal only)
|
||||
volumes:
|
||||
- kube-config:/home/candidate/.kube # Shared volume for Kubernetes config
|
||||
- kube-config:/home/candidate/.kube # Shared volume for Kubernetes config
|
||||
deploy:
|
||||
resources:
|
||||
limits:
|
||||
cpus: '1'
|
||||
cpus: "1"
|
||||
reservations:
|
||||
cpus: '0.5'
|
||||
cpus: "0.5"
|
||||
memory: 512M
|
||||
networks:
|
||||
- ckx-network
|
||||
@@ -115,7 +115,7 @@ services:
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 3
|
||||
|
||||
|
||||
# Remote Terminal Service
|
||||
remote-terminal:
|
||||
image: nishanb/ck-x-simulator-remote-terminal:latest
|
||||
@@ -123,14 +123,14 @@ services:
|
||||
context: ./remote-terminal
|
||||
hostname: remote-terminal
|
||||
expose:
|
||||
- "22" # SSH port (internal only)
|
||||
- "22" # SSH port (internal only)
|
||||
deploy:
|
||||
resources:
|
||||
limits:
|
||||
cpus: '0.5'
|
||||
cpus: "0.5"
|
||||
memory: 512M
|
||||
reservations:
|
||||
cpus: '0.2'
|
||||
cpus: "0.2"
|
||||
memory: 256M
|
||||
networks:
|
||||
- ckx-network
|
||||
@@ -139,27 +139,27 @@ services:
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 3
|
||||
|
||||
|
||||
# KIND Kubernetes Cluster
|
||||
k8s-api-server: # Service name that will be used for DNS resolution
|
||||
k8s-api-server: # Service name that will be used for DNS resolution
|
||||
image: nishanb/ck-x-simulator-cluster:latest
|
||||
build:
|
||||
context: ./kind-cluster
|
||||
container_name: kind-cluster
|
||||
hostname: k8s-api-server
|
||||
privileged: true # Required for running containers inside KIND
|
||||
privileged: true # Required for running containers inside KIND
|
||||
expose:
|
||||
- "6443:6443"
|
||||
- "6443"
|
||||
- "22"
|
||||
volumes:
|
||||
- kube-config:/home/candidate/.kube # Shared volume for Kubernetes config
|
||||
- kube-config:/home/candidate/.kube # Shared volume for Kubernetes config
|
||||
deploy:
|
||||
resources:
|
||||
limits:
|
||||
cpus: '2'
|
||||
cpus: "2"
|
||||
memory: 4G
|
||||
reservations:
|
||||
cpus: '1'
|
||||
cpus: "1"
|
||||
memory: 2G
|
||||
networks:
|
||||
- ckx-network
|
||||
@@ -183,10 +183,10 @@ services:
|
||||
deploy:
|
||||
resources:
|
||||
limits:
|
||||
cpus: '0.3'
|
||||
cpus: "0.3"
|
||||
memory: 256M
|
||||
reservations:
|
||||
cpus: '0.1'
|
||||
cpus: "0.1"
|
||||
memory: 128M
|
||||
healthcheck:
|
||||
test: ["CMD", "redis-cli", "ping"]
|
||||
@@ -222,10 +222,10 @@ services:
|
||||
deploy:
|
||||
resources:
|
||||
limits:
|
||||
cpus: '0.5'
|
||||
cpus: "0.5"
|
||||
memory: 512M
|
||||
reservations:
|
||||
cpus: '0.2'
|
||||
cpus: "0.2"
|
||||
memory: 256M
|
||||
healthcheck:
|
||||
test: ["CMD", "wget", "-q", "-O", "-", "http://localhost:3000"]
|
||||
@@ -239,4 +239,4 @@ networks:
|
||||
driver: bridge
|
||||
|
||||
volumes:
|
||||
kube-config: # Shared volume for Kubernetes configuration
|
||||
kube-config: # Shared volume for Kubernetes configuration
|
||||
|
||||
@@ -11,7 +11,7 @@ Thank you for your interest in contributing! Here's how you can help:
|
||||
|
||||
## Community
|
||||
|
||||
- Join our [Telegram Community](https://t.me/ckxdev)
|
||||
- Join our [Discord Community](https://discord.gg/24HtTEjA)
|
||||
- Star the repository if you find it helpful
|
||||
|
||||
## Important Rules
|
||||
@@ -35,7 +35,7 @@ Thank you for your interest in contributing! Here's how you can help:
|
||||
|
||||
## Questions?
|
||||
|
||||
Check our [FAQ](docs/FAQ.md) or join our [Telegram Community](https://t.me/ckxdev).
|
||||
Check our [FAQ](docs/FAQ.md) or join our [Discord Community](https://discord.gg/24HtTEjA).
|
||||
|
||||
## License
|
||||
|
||||
|
||||
@@ -11,10 +11,15 @@ fi
|
||||
# Verify container names
|
||||
NGINX_CONTAINER=$(kubectl get pod sidecar-pod -n troubleshooting -o jsonpath='{.spec.containers[?(@.name=="nginx")].name}' 2>/dev/null)
|
||||
SIDECAR_CONTAINER=$(kubectl get pod sidecar-pod -n troubleshooting -o jsonpath='{.spec.containers[?(@.name=="sidecar")].name}' 2>/dev/null)
|
||||
SIDECAR_INITCONTAINER=$(kubectl get pod sidecar-pod -n troubleshooting -o jsonpath='{.spec.initContainers[?(@.name=="sidecar")].name}' 2>/dev/null)
|
||||
SIDECAR_INITCONTAINER_CONDITION=$(kubectl get pod sidecar-pod -n troubleshooting -o jsonpath='{.spec.initContainers[?(@.name=="sidecar")].restartPolicy}' 2>/dev/null)
|
||||
|
||||
if [ -n "$NGINX_CONTAINER" ] && [ -n "$SIDECAR_CONTAINER" ]; then
|
||||
echo "Success: Pod has both 'nginx' and 'sidecar' containers"
|
||||
exit 0
|
||||
elif [ -n "$NGINX_CONTAINER" ] && [ -n "$SIDECAR_INITCONTAINER" ] && [ "$SIDECAR_INITCONTAINER_CONDITION" = "Always" ]; then
|
||||
echo "Success: Pod has 'nginx' container and 'sidecar' init container with restartPolicy 'Always'"
|
||||
exit 0
|
||||
else
|
||||
echo "Error: Pod does not have the required container names ('nginx' and 'sidecar')"
|
||||
echo "Found containers with names: $(kubectl get pod sidecar-pod -n troubleshooting -o jsonpath='{.spec.containers[*].name}' 2>/dev/null)"
|
||||
|
||||
@@ -11,7 +11,6 @@ class MetricService {
|
||||
this.METRIC_SERVER_URL = 'https://ck-x-metric-server.onrender.com/api/v1/collect';
|
||||
this.TRACK_METRICS = process.env.TRACK_METRICS ? process.env.TRACK_METRICS === 'true' : true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Send metrics to the metric server for analytics purposes do not collect any personal data
|
||||
@@ -20,6 +19,8 @@ class MetricService {
|
||||
* @returns {Promise} - Response from the metric server
|
||||
*/
|
||||
async sendMetrics(examId, data) {
|
||||
data.cloud = "ck-x-cloud";
|
||||
data.version = "1.0.0";
|
||||
if (!this.TRACK_METRICS) return;
|
||||
try {
|
||||
const metricData = {
|
||||
|
||||
@@ -63,6 +63,7 @@ sleep 5
|
||||
|
||||
#wait till api-server is ready
|
||||
while ! kubectl get nodes > /dev/null 2>&1; do
|
||||
log "API server is not ready, retrying..."
|
||||
sleep 5
|
||||
done
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ if ! command -v k3d &> /dev/null; then
|
||||
|
||||
# Retry k3d installation up to 5 times
|
||||
INSTALL_ATTEMPTS=0
|
||||
while [ $INSTALL_ATTEMPTS -lt 5 ]; do
|
||||
while [ $INSTALL_ATTEMPTS -lt 99999 ]; do
|
||||
INSTALL_ATTEMPTS=$((INSTALL_ATTEMPTS+1))
|
||||
echo "$(date '+%Y-%m-%d %H:%M:%S') | Installation attempt $INSTALL_ATTEMPTS"
|
||||
|
||||
@@ -27,8 +27,8 @@ if ! command -v k3d &> /dev/null; then
|
||||
echo "$(date '+%Y-%m-%d %H:%M:%S') | k3d successfully installed"
|
||||
break
|
||||
else
|
||||
echo "$(date '+%Y-%m-%d %H:%M:%S') | k3d installation failed. Retrying in 5 seconds..."
|
||||
sleep 5
|
||||
echo "$(date '+%Y-%m-%d %H:%M:%S') | k3d installation failed. Retrying in 10 seconds..."
|
||||
sleep 10
|
||||
fi
|
||||
done
|
||||
|
||||
@@ -54,13 +54,9 @@ metadata:
|
||||
name: $CLUSTER_NAME
|
||||
servers: 1
|
||||
agents: $NUM_WORKERS
|
||||
ports:
|
||||
- port: "$API_PORT:6443"
|
||||
nodeFilters:
|
||||
- loadbalancer
|
||||
kubeAPI:
|
||||
host: "127.0.0.1"
|
||||
hostPort: "$API_PORT"
|
||||
hostPort: "6443"
|
||||
options:
|
||||
k3s:
|
||||
extraArgs:
|
||||
@@ -107,10 +103,15 @@ echo "$(date '+%Y-%m-%d %H:%M:%S') | ✅ K3d cluster '$CLUSTER_NAME' is up and r
|
||||
|
||||
echo "$(date '+%Y-%m-%d %H:%M:%S') | Docker and KIND environment is ready for use"
|
||||
|
||||
k3d kubeconfig get $CLUSTER_NAME > /home/candidate/.kube/kubeconfig
|
||||
echo "Kubeconfig file created: /home/candidate/.kube/kubeconfig"
|
||||
|
||||
# Save kubeconfig and set API server address
|
||||
cp /home/candidate/.kube/config /home/candidate/.kube/kubeconfig
|
||||
sed -i 's|server: https://127\.0\.0\.1:\([0-9]*\)|server: https://k8s-api-server:\1|' /home/candidate/.kube/kubeconfig
|
||||
|
||||
echo "Kubeconfig file content:"
|
||||
cat /home/candidate/.kube/kubeconfig
|
||||
|
||||
export KUBECONFIG=/home/candidate/.kube/kubeconfig
|
||||
|
||||
#info on config file setup done
|
||||
|
||||
@@ -7,6 +7,11 @@ map $http_upgrade $connection_upgrade {
|
||||
server {
|
||||
listen 80;
|
||||
|
||||
# Disable caching globally
|
||||
add_header Cache-Control "no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0" always;
|
||||
add_header Pragma "no-cache" always;
|
||||
add_header Expires "0" always;
|
||||
|
||||
# Root location redirects to webapp
|
||||
location / {
|
||||
proxy_pass http://webapp:3000/;
|
||||
@@ -18,6 +23,7 @@ server {
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_cache_bypass $http_upgrade;
|
||||
proxy_no_cache 1;
|
||||
}
|
||||
|
||||
# Facilitator API endpoint
|
||||
@@ -29,6 +35,7 @@ server {
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_cache_bypass $http_upgrade;
|
||||
proxy_no_cache 1;
|
||||
}
|
||||
|
||||
# VNC WebSocket proxy with improved WebSocket handling
|
||||
@@ -39,6 +46,7 @@ server {
|
||||
proxy_set_header Connection $connection_upgrade;
|
||||
proxy_set_header Host $host;
|
||||
proxy_cache_bypass $http_upgrade;
|
||||
proxy_no_cache 1;
|
||||
proxy_read_timeout 86400;
|
||||
proxy_send_timeout 86400;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
@@ -54,6 +62,7 @@ server {
|
||||
proxy_set_header Connection $connection_upgrade;
|
||||
proxy_set_header Host $host;
|
||||
proxy_cache_bypass $http_upgrade;
|
||||
proxy_no_cache 1;
|
||||
proxy_read_timeout 86400;
|
||||
proxy_send_timeout 86400;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
|
||||
@@ -45,4 +45,4 @@ RUN chmod +x /usr/local/bin/startup.sh
|
||||
|
||||
COPY agent.py /tmp/agent.py
|
||||
|
||||
RUN sed -i '/### every exit != 0 fails the script/a /usr/local/bin/startup.sh' /dockerstartup/vnc_startup.sh
|
||||
RUN sed -i '/### every exit != 0 fails the script/a /usr/local/bin/startup.sh' /dockerstartup/vnc_startup.sh
|
||||
|
||||
51
remote-desktop/Dockerfile.qemu
Normal file
51
remote-desktop/Dockerfile.qemu
Normal file
@@ -0,0 +1,51 @@
|
||||
# Base Image (x86_64 build only)
|
||||
FROM nishanb/ck-x-simulator-vnc-base:v3
|
||||
|
||||
# --- Add QEMU for ARM emulation ---
|
||||
# This lets the container run on ARM hosts even if the base image is amd64
|
||||
COPY --from=multiarch/qemu-user-static:latest /usr/bin/qemu-* /usr/bin/
|
||||
|
||||
# Switch to root user for installations
|
||||
USER 0
|
||||
|
||||
# Update and install required dependencies
|
||||
RUN apt-get update && apt-get install -y \
|
||||
curl \
|
||||
wget \
|
||||
apt-transport-https \
|
||||
ca-certificates \
|
||||
gnupg \
|
||||
lsb-release \
|
||||
software-properties-common \
|
||||
ssh-client \
|
||||
telnet \
|
||||
nano \
|
||||
vim \
|
||||
xclip \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# create candidate user
|
||||
RUN useradd -m candidate
|
||||
|
||||
# set hostname as terminal
|
||||
RUN echo "export HOSTNAME=terminal" >> /headless/.bashrc
|
||||
# set terminal to bash
|
||||
RUN echo "export TERM=xterm" >> /headless/.bashrc
|
||||
|
||||
# when shell opens, switch to candidate user
|
||||
RUN echo "cd /home/candidate && su candidate" >> /headless/.bashrc
|
||||
|
||||
# disable asking for ssh host verification
|
||||
RUN mkdir -p /home/candidate/.ssh && \
|
||||
echo "StrictHostKeyChecking no" >> /home/candidate/.ssh/config && \
|
||||
echo "UserKnownHostsFile /dev/null" >> /home/candidate/.ssh/config
|
||||
|
||||
# Copy startup script
|
||||
COPY startup.sh /usr/local/bin/startup.sh
|
||||
RUN chmod +x /usr/local/bin/startup.sh
|
||||
|
||||
# Copy agent
|
||||
COPY agent.py /tmp/agent.py
|
||||
|
||||
# Inject startup script into vnc_startup.sh
|
||||
RUN sed -i '/### every exit != 0 fails the script/a /usr/local/bin/startup.sh' /dockerstartup/vnc_startup.sh
|
||||
@@ -4,6 +4,7 @@
|
||||
echo "Starting CKAD VNC service at $(date)"
|
||||
|
||||
echo "echo 'Use Ctrl + Shift + C for copying and Ctrl + Shift + V for pasting'" >> /home/candidate/.bashrc
|
||||
echo "alias kubectl='echo \"kubectl not available here. Solve this question on the specified instance\"'" >> /home/candidate/.bashrc
|
||||
|
||||
# Run in the background - don't block the main container startup
|
||||
python3 /tmp/agent.py &
|
||||
|
||||
@@ -41,7 +41,7 @@ irm https://raw.githubusercontent.com/nishanb/CK-X/master/scripts/install.ps1 |
|
||||
1. Clone the repository:
|
||||
```bash
|
||||
git clone https://github.com/nishanb/CK-X.git
|
||||
cd ck-x
|
||||
cd CK-X
|
||||
```
|
||||
|
||||
2. Build and start the services using Docker Compose:
|
||||
@@ -138,4 +138,4 @@ docker compose down
|
||||
# Remove downloaded files
|
||||
cd ..
|
||||
rm -rf ck-x-simulator
|
||||
```
|
||||
```
|
||||
|
||||
@@ -206,7 +206,7 @@ try {
|
||||
|
||||
# Function to open browser
|
||||
function Open-Browser {
|
||||
$url = "http://localhost:30080"
|
||||
$url = "http://localhost:30080/"
|
||||
Write-ColorOutput "Opening Browser" "Blue"
|
||||
Write-ColorOutput "==============================================================" "Cyan"
|
||||
|
||||
@@ -221,7 +221,7 @@ try {
|
||||
return $true
|
||||
} catch {
|
||||
Write-ColorOutput "Could not automatically open browser. Please visit:" "Yellow"
|
||||
Write-ColorOutput "http://localhost:30080" "Green"
|
||||
Write-ColorOutput "https://play.sailor.sh/" "Green"
|
||||
return $false
|
||||
}
|
||||
}
|
||||
@@ -340,6 +340,10 @@ try {
|
||||
Write-ColorOutput "docker system prune -a" "Green"
|
||||
Write-ColorOutput "To remove only CK-X images: " -NoNewline
|
||||
Write-ColorOutput "docker compose down --rmi all" "Green"
|
||||
Write-ColorOutput "To access CK-X Simulator: " -NoNewline
|
||||
Write-ColorOutput "https://play.sailor.sh/" "Green"
|
||||
Write-ColorOutput "To access CK-X Simulator locally use: " -NoNewline
|
||||
Write-ColorOutput "http://localhost:30080/" "Green"
|
||||
Write-Host ""
|
||||
Write-ColorOutput "Thank you for installing CK-X Simulator!" "Cyan"
|
||||
}
|
||||
|
||||
@@ -142,7 +142,7 @@ wait_for_service() {
|
||||
|
||||
# Function to open browser
|
||||
open_browser() {
|
||||
local url="http://localhost:30080"
|
||||
local url="http://localhost:30080/"
|
||||
echo -e "${BLUE}Opening Browser${NC}"
|
||||
echo -e "${CYAN}==============================================================${NC}"
|
||||
|
||||
@@ -162,7 +162,7 @@ open_browser() {
|
||||
fi
|
||||
|
||||
echo -e "${YELLOW}Could not automatically open browser. Please visit:${NC}"
|
||||
echo -e "${GREEN}http://localhost:30080${NC}"
|
||||
echo -e "${GREEN}https://play.sailor.sh/${NC}"
|
||||
return 1
|
||||
}
|
||||
|
||||
@@ -225,6 +225,8 @@ main() {
|
||||
echo -e "${YELLOW}To Restart CK-X:${NC} ${GREEN}docker compose restart${NC}"
|
||||
echo -e "${YELLOW}To clean up all containers and images:${NC} ${GREEN}docker system prune -a${NC}"
|
||||
echo -e "${YELLOW}To remove only CK-X images:${NC} ${GREEN}docker compose down --rmi all${NC}"
|
||||
echo -e "${YELLOW}To access CK-X Simulator:${NC} ${GREEN}https://play.sailor.sh/${NC}"
|
||||
echo -e "${YELLOW}To access CK-X Simulator locally use:${NC} ${GREEN}http://localhost:30080/${NC}"
|
||||
echo
|
||||
echo -e "${CYAN}Thank you for installing CK-X Simulator!${NC}"
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user