Deployment¶
Docker¶
Default bridge network¶
The simplest way to run canon-proxy in Docker. Docker's iptables MASQUERADE rewrites the container source IP to the host's LAN IP, so the camera sees a same-subnet connection and accepts the PTP/IP handshake.
Persist the database
Set database.dsn: /data/canon-proxy.db in your config.yaml so the SQLite database is written inside the /data volume. Using the default ./canon-proxy.db path places the file in the container filesystem and the database will be lost when the container is recreated.
docker run --rm \
-v "$(pwd)/config.yaml:/app/config.yaml:ro" \
-v canon-proxy-data:/data \
-p 9090:9090 \
ghcr.io/pacorreia/canon-proxy:latest
Host network (alternative)¶
Use --network host if bridge NAT is not available (e.g. certain NAS environments or when the camera requires strict same-subnet enforcement):
docker run --rm \
--network host \
-v "$(pwd)/config.yaml:/app/config.yaml:ro" \
-v canon-proxy-data:/data \
ghcr.io/pacorreia/canon-proxy:latest
Docker Compose¶
services:
canon-proxy:
image: ghcr.io/pacorreia/canon-proxy:latest
ports:
- "9090:9090"
volumes:
- ./config.yaml:/app/config.yaml:ro
- canon-proxy-data:/data
restart: unless-stopped
volumes:
canon-proxy-data:
Kubernetes (Helm)¶
Add the OCI chart¶
helm install canon-proxy \
oci://ghcr.io/pacorreia/charts/canon-proxy \
--version 0.1.0 \
--namespace canon-proxy \
--create-namespace \
-f my-values.yaml
Key values¶
# my-values.yaml
config:
camera:
host: "192.168.2.70"
port: 15740
poll_interval: 5s
upload:
workers: 1
backend: smb
web:
listen: ":9090"
# SMB credentials — stored in a Secret
secret:
smb:
password: "mysecretpassword"
# Persistent volume for the SQLite database
persistence:
enabled: true
size: 1Gi
# Traefik IngressRoute
ingress:
enabled: true
host: "canon-proxy.example.com"
tls: true
# Set to true only if your camera is NOT reachable via the cluster CNI.
# When true, the pod shares the node's network namespace.
hostNetwork: false
hostNetwork and camera access
If the Canon camera is on the same LAN as your Kubernetes nodes but not reachable from the pod network (no routing / CNI isolation), set hostNetwork: true to share the node's network namespace. The camera will then see the node's real IP.
Upgrade¶
helm upgrade canon-proxy \
oci://ghcr.io/pacorreia/charts/canon-proxy \
--version 0.2.0 \
--reuse-values
Building from source¶
git clone https://github.com/pacorreia/canon-proxy.git
cd canon-proxy
# Build for the local OS
CGO_ENABLED=0 go build -o canon-proxy ./cmd/canon-proxy
# Cross-compile for Linux ARM64
CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build -o canon-proxy-linux-arm64 ./cmd/canon-proxy
Build the Docker image¶
The Dockerfile uses a distroless nonroot runtime image — no shell, minimal attack surface.