C64 Gate is a Linux gateway for Commodore 64 Ultimate devices, packaged as a single Docker image
It sits between the device and the rest of the network, secures inbound and outbound traffic via TLS, and gives you packet capture, structured logs, and a small control plane.
Note
This project is EXPERIMENTAL and not yet fully functional.
C64 Gate sits between the Commodore 64 Ultimate and the outside world.
It protects the device by securing inbound connections and upgrading outbound traffic whenever possible.
When the C64 Ultimate makes a network request, C64 Gate attempts to upgrade insecure HTTP connections to HTTPS automatically.
flowchart LR
Internet["Internet Service"]
Gate["C64 Gate"]
C64["C64 Ultimate"]
C64 -->|"1. HTTP request"| Gate
Gate -->|"2. Try HTTPS first"| Internet
Internet -->|"3. HTTPS response"| Gate
Gate -->|"4. HTTP response"| C64
External clients connect securely to C64 Gate.
The gateway then communicates with the C64 Ultimate on its internal network.
flowchart LR
Client["Client"]
Gate["C64 Gate"]
C64["C64 Ultimate"]
Client -->|"1. HTTPS / FTPS request"| Gate
Gate -->|"2. HTTP / FTP request"| C64
C64 -->|"3. HTTP / FTP Response"| Gate
Gate -->|"4. HTTPS / FTPS response"| Client
- One container image for the complete gateway runtime
- Linux-native firewalling with nftables
- DHCP and local naming for the device-side network
- HTTPS and FTPS front ends for inbound access
- Automatic outbound HTTP to HTTPS upgrade when possible
- Packet capture with Wireshark tooling behind the scenes
- Canonical JSON logs for traffic and daemon events
- A small FastAPI control plane for health, readiness, and dashboard views
For more information see the Architecture document.
If you only want a quick proof that the project works, the shortest useful path is:
- Install Docker on a Linux machine.
- Run
docker compose up --buildin this repository. - Open
https://127.0.0.1:8443/v1/versionand confirm you get a JSON response from the HTTPS relay. - If you also want management status, open
https://127.0.0.1:8443/healthandhttps://127.0.0.1:8443/readywith the configured dashboard credentials.
That path uses the same production image the tests validate. By default, the Compose setup runs in simulation mode so you can explore the system without attaching a real device or changing host networking more than necessary.
If Docker is new to you, use the official installation guides rather than learning that from this README:
Minimum requirements:
- Linux host
- Docker with the Compose plugin
Start the stack:
docker compose up --buildAfter that command starts successfully, the exact endpoint to hit first is:
https://127.0.0.1:8443/v1/version
That is the clearest end-to-end check that the HTTPS facade is up and the relayed REST path is working. In the default Compose simulation mode, it should return JSON shaped like:
{"device":"c64u-sim","transport":"https-relay","version":"0.0.1"}Run a specific published image from GHCR locally:
mkdir -p data/caddy data/logs data/pcap
chmod 0777 data/caddy data/logs data/pcap
docker run -d \
--name c64gate-ghcr \
--cap-drop ALL \
--cap-add NET_ADMIN \
--cap-add NET_RAW \
--cap-add SYS_CHROOT \
--read-only \
--tmpfs /run \
--tmpfs /tmp \
-e C64GATE_SIMULATION_MODE=1 \
-e C64GATE_FTPS_PUBLIC_HOST=127.0.0.1 \
-e C64GATE_DASHBOARD_PASSWORD=changeme \
-p 127.0.0.1:8443:8443 \
-p 127.0.0.1:30000-30009:30000-30009 \
-v "$PWD/data/caddy:/var/lib/c64gate/caddy" \
-v "$PWD/data/logs:/var/lib/c64gate/logs" \
-v "$PWD/data/pcap:/var/lib/c64gate/pcap" \
ghcr.io/chrisgleissner/c64gate:0.0.1If you want the published image to front a real C64 REST endpoint instead of the simulation target, set C64GATE_SIMULATION_MODE=0 and provide C64GATE_REST_BACKEND_URL=http://<c64u-ip>.
The C64 Ultimate must not have any direct network path to your normal LAN or the Internet. If it does, the gateway cannot guarantee that all outbound traffic is inspected and upgraded through C64 Gate.
To guarantee that all outbound traffic flows through the gate:
- Disable Wi-Fi on the C64 Ultimate.
- Connect the C64 Ultimate by Ethernet only to the gateway host's device-side network.
- Ensure the gateway host has a separate uplink path to the outside network.
- Make the C64 Ultimate receive its IP configuration and default gateway from C64 Gate.
- Do not connect the C64 Ultimate to any other switch, Wi-Fi, or routed segment in parallel.
Two practical hardware topologies are recommended:
- Raspberry Pi gateway: Use one Ethernet interface on the Pi for the C64U device-side link and use the Pi's Wi-Fi or a second Ethernet adapter as the uplink. The C64U should be connected only to the Pi-facing Ethernet segment.
- PC with two network interfaces: Use one NIC for the isolated C64U-facing network and a second NIC for the uplink to your normal LAN or Internet. Do not bridge those interfaces outside the gateway runtime.
In both setups, the important property is the same: the C64U has exactly one physical path off-device, and that path terminates at the C64 Gate host.
To proxy a real C64 REST API instead of the default local simulation target, set C64GATE_REST_BACKEND_URL to the device's plain HTTP endpoint before starting Compose. Example:
C64GATE_REST_BACKEND_URL=http://192.168.1.167 docker compose up --buildUseful endpoints after startup:
https://127.0.0.1:8443/v1/versionis the first endpoint to test afterdocker compose up --buildhttps://127.0.0.1:8443/api/v1/infois the HTTPS REST facade information endpointhttps://127.0.0.1:8443/healthis the authenticated liveness endpointhttps://127.0.0.1:8443/readyis the authenticated readiness endpoint
Management access notes:
- The default Compose profile no longer publishes
8081; management traffic must enter through the HTTPS facade. /health,/ready, and/dashboard/*require the configured dashboard credentials.C64GATE_DASHBOARD_PASSWORDmust be changed fromchangemeoutside simulation mode or the runtime will refuse to start.
If you want host port 443 instead of 8443, set C64GATE_HTTPS_HOST_PORT=443 before starting Compose. On rootless Docker hosts, publishing 443 may require lowering net.ipv4.ip_unprivileged_port_start.
For a normal https://127.0.0.1/... experience in Chrome without certificate warnings, use the project helper scripts:
sudo ./scripts/setup-host-https.sh
C64GATE_HTTPS_HOST_PORT=443 C64GATE_REST_BACKEND_URL=http://192.168.1.167 docker compose up -d --build
./scripts/trust-caddy-local-ca.shThis keeps Docker rootless, keeps the container itself unprivileged, and applies the minimum host changes needed for a conventional local HTTPS entry point.
For local FTPS through the same loopback bind, keep the published passive range 30000-30009 and C64GATE_FTPS_PUBLIC_HOST=127.0.0.1.
The runtime includes an internal FTPS relay so protected passive transfers work under rootless Docker without requiring a rootful daemon.
Stop the stack:
docker compose downThe default Compose file mounts logs and packet captures into data/logs and data/pcap so you can inspect outputs from the host.
The Caddy local CA state under data/caddy should be treated as secret material and kept out of broad backups or sharing workflows.
Use the root build script for the standard workflows:
./build help
./build test
./build image
./build smoke
./build ciPython dependency installs are enforced from the hash-locked manifests requirements.lock.txt and requirements-dev.lock.txt.
You only need Python if you want to run the local lint and test workflow outside the containerized smoke path.
The most useful follow-on documents are:
- doc/developer.md for local developer workflows
- doc/architecture.md for the system design and locked technology choices
- doc/traceability-matrix.yaml for requirement-to-code-to-test coverage
- v1 is Linux only.
- The project is designed as a router-mode gateway, not a generic cross-platform desktop app.
- Real firewall enforcement, DHCP service, and device traffic capture are best exercised on a disposable Linux host or an isolated lab network.
- The runtime depends on Linux capabilities such as
NET_ADMIN,NET_RAW, andSYS_CHROOT. - Strict TLS mode is available through
C64GATE_STRICT_TLS_MODE=1; default fallback HTTP remains an exception path for compatibility and should be limited to trusted environments. - Telnet and other plaintext paths remain compatibility features and should not be exposed outside a trusted administrative enclave.
- macOS or Windows runtime support
- bridge mode
- DNS policy enforcement
- cloud-hosted control plane services
- large analytics platforms
