6.5 KiB
Connectivity Test Server
A simple HTTP server for connectivity testing. It can be run from the command line or in a container.
The Python version relies only on Python's standard library, so it should work in any environment with Python installed. The Node.js version also relies only on the standard library, so it should work in any environment with Node.js installed. The Go version also relies only on the standard library, so it should work in any environment with Go installed.
It displays a simple HTML or plain-text page with the client's IP address and any detected X-* headers.
Disclaimer
The ok-server scripts were generated using AI under human supervision. The owner of the repository is not responsible for any issues that may arise from using the AI-generated code.
Usage
Command Line
To run the server from the command line:
python3 ok-server.py
python3 ok-server.py --look basic
python3 ok-server.py --bind 127.0.0.1 --port 8080 --look tailwind
python3 ok-server.py --pem /path/to/bundle.pem
python3 ok-server.py --pem /path/to/bundle.pem --tls-port 9443
--look accepts basic, nice, bootstrap, or tailwind.
You can override the look per request with the look query parameter, for example:
http://localhost:8080/?look=tailwind
--pem accepts a path to a PEM file containing the certificate chain and private key.
When provided, the server listens on both HTTP (--port, default 8080) and HTTPS (--tls-port, default 8443).
node ok-server.mjs
node ok-server.mjs --look basic
node ok-server.mjs --bind 127.0.0.1 --port 8080 --look tailwind
node ok-server.mjs --pem /path/to/bundle.pem
node ok-server.mjs --pem /path/to/bundle.pem --tls-port 9443
go run ok-server.go
go run ok-server.go --look basic
go run ok-server.go --bind 127.0.0.1 --port 8080 --look tailwind
go run ok-server.go --pem /path/to/bundle.pem
go run ok-server.go --pem /path/to/bundle.pem --tls-port 9443
Connect to the server using a web browser or a tool like curl:
curl -si "http://localhost:8080"
Building a Go binary
Cross-compile for any platform from any machine:
# Linux amd64
GOOS=linux GOARCH=amd64 go build -o ok-server-linux-amd64 ok-server.go
# Linux arm64
GOOS=linux GOARCH=arm64 go build -o ok-server-linux-arm64 ok-server.go
# macOS arm64 (Apple Silicon)
GOOS=darwin GOARCH=arm64 go build -o ok-server-darwin-arm64 ok-server.go
# macOS amd64 (Intel)
GOOS=darwin GOARCH=amd64 go build -o ok-server-darwin-amd64 ok-server.go
# Windows amd64
GOOS=windows GOARCH=amd64 go build -o ok-server-windows-amd64.exe ok-server.go
Docker
Use the included Dockerfile to build and run the server in a Docker container:
docker build -t ok-server .
docker run -d --restart unless-stopped --name ok-server --cpus=1 --memory=256m -p 8080:8080 ok-server
This will start the server and expose it on port 8080. The container will run until stopped. You can restart it with docker start ok-server, or remove it with docker rm ok-server.
Container CLI on a Mac
container builder stop
container builder start -c 4 -m 1G
container build -t ok-server .
container run --rm -d --name ok-server -c 1 -m 256m -p 8080:8080 ok-server
This will start the server and expose it on port 8080. The container will run until stopped, and will be removed when stopped. You can stop it with container stop ok-server.
nerdctl with BuildKit on a k3s server
Build the image directly into the containerd instance used by k3s:
sudo nerdctl build -t ok-server .
sudo nerdctl images
On a single-node k3s cluster the image is now available to the kubelet without a
registry. The k3s/deployment.yaml Deployment references
it with imagePullPolicy: Never:
kubectl apply -f k3s/deployment.yaml
Expose the app with one of the two options below.
Option 1: Traefik Ingress
k3s includes the Traefik ingress controller. The ClusterIP Service and Ingress
in k3s/expose-ingress.yaml expose the app over HTTPS
on port 443 for the host name ok-server.example.org. Change the host value
in the Ingress to your own FQDN and point its DNS record at the node's IP
address:
kubectl apply -f k3s/expose-ingress.yaml
curl -si "https://ok-server.example.org/"
Without a DNS record you can still test the host rule by mapping the name to
the node's IP address on the curl command line (-k skips certificate
verification, since no certificate can be issued before DNS works):
curl -sik --resolve ok-server.example.org:443:<node-ip> "https://ok-server.example.org/"
The TLS certificate comes from a Traefik certificate resolver named le,
referenced by the traefik.ingress.kubernetes.io/router.tls.certresolver
annotation on the Ingress. Configuring the resolver is out of scope for this
project; it is expected to already exist in your Traefik installation. If your
resolver has a different name, change the annotation value accordingly. To
serve plain HTTP instead, remove the three traefik.ingress.kubernetes.io
annotations from the Ingress.
By default the app sees a cluster-internal address (for example 10.42.0.1)
instead of the real client IP, because the Traefik Service runs with
externalTrafficPolicy: Cluster. The HelmChartConfig in
k3s/traefik-config.yaml sets
externalTrafficPolicy: Local on the Traefik Service to preserve the client
IP.
A cluster can hold only one HelmChartConfig named traefik, so first check
whether one already exists:
kubectl get helmchartconfig traefik -n kube-system
If it does not exist, apply the file as is:
kubectl apply -f k3s/traefik-config.yaml
If it already exists, do not apply the file, as it would replace the existing
Traefik settings. Instead, add externalTrafficPolicy: Local under the
service.spec section of the existing valuesContent:
kubectl edit helmchartconfig traefik -n kube-system
Option 2: ServiceLB
k3s also includes the ServiceLB load balancer. The single LoadBalancer
Service in k3s/expose-servicelb.yaml exposes the
app on port 8080 of the node's IP address, without an Ingress. The Service sets
externalTrafficPolicy: Local so the app sees the real client IP:
kubectl apply -f k3s/expose-servicelb.yaml
curl -si "http://<node-ip>:8080"
On a multi-node cluster, push the image to a registry instead, so every node can pull it.
License
This project is licensed under the MIT License. See the LICENSE file for details.