Preview (0.x) — not production-ready. Use at your own risk.
Open Source · Preview · Go 1.25 v0.2.33

GoProxify

The reverse proxy that guides every visitor to the right app.
Publish your services. GoProxify makes them reachable, protected, and easy to manage — without the jargon.

Open Source Docker Portainer Admin UI EN · FR · ES · DE

What is a reverse proxy for?

A reverse proxy lets you publish several websites on the internet — each with its own address (https://blog…, https://shop…, https://app…) — while the applications themselves stay behind, out of direct reach.

1

Several sites, several addresses

You run multiple apps or containers. Visitors open a normal web address for each site. They never talk to the containers directly.

2

One front door for all of them

GoProxify receives every visit and opens the right door: blog traffic goes to the blog, shop traffic to the shop — according to the rules you set.

3

You stay in control

From one place you decide which sites are public, which need a login, and how to keep them available if a machine fails.

How GoProxify works

Three simple pieces that work together: a control panel, traffic gateways, and a helper that watches your containers.

Admin

Your control panel

A clear web interface to create routes, manage domains, invite teammates, and see what is going on — in your language.

Gateway

The traffic gateways

Gateways welcome visitors on your public addresses and send them to the right site in the fleet. You can run several so traffic keeps flowing if one machine goes down.

Agent + Portainer

Your container fleet, connected

The Agent links to Portainer (or Docker) to discover containers and keep routes up to date as your fleet grows or changes.

Reliability

Keeps working when things break

Gateways remember their settings and keep serving your sites even if the Admin is temporarily offline. A second gateway covers for the first.

Security

Protect what you publish

Limit abusive traffic, block threats, and require login when needed — so your apps are not left wide open on the internet.

Visibility

See what happens

Live traffic views, clear logs, and alerts so you know when something is wrong — without digging through server files.

Access

Reach servers from the browser

Invite operators to open a secure terminal to VMs or containers when they need it — without sharing passwords casually.

A typical setup

One Admin to steer everything, two gateways to welcome visitors, and one Agent linked to Portainer to follow your container fleet. Visitors reach those sites through normal internet addresses (https://…).

goproxify — example layout
GoProxify reverse proxy layout Visitors open https addresses, reach two gateways, and land on sites in the container fleet. One Admin configures both gateways. One Agent connects to Portainer. VISITORS Open your sites online https://blog… · https://shop… via internet addresses GATEWAY 1 Routes each site Primary public entry GATEWAY 2 Same role, spare Takes over if gateway 1 fails share the load ADMIN One control panel Configure both gateways Users · domains · alerts pushes settings AGENT Watches the fleet Reports new containers updates routes PORTAINER Manages containers Start · stop · deploy connected Your published sites blog shop app reached via https://… manages the fleet 1 Admin · 2 gateways · 1 Agent + Portainer · N sites

Get started in 5 minutes

A ready-to-run Admin + Core + Agent stack. Pick your method.

Generates hex-32 secrets, writes .env (chmod 600), checks Docker / ports, then starts Admin + Core + Agent.

shell
# Download then run (inspect before execute)
$ curl -fsSL https://github.com/Vincamok/goproxify/raw/public/main/scripts/quickstart.sh -o quickstart.sh
$ bash quickstart.sh

Admin UI → http://localhost:9443. Variants (run alone, never paste with the block above): bash quickstart.sh --print-secrets · bash quickstart.sh --env-only

Official GHCR images with floating :preview tag (0.x). Optional SemVer pin via versions.json.

shell
# 1. Fetch quickstart + env template
$ curl -LO https://github.com/Vincamok/goproxify/raw/public/main/docker-compose.quickstart.yml
$ curl -LO https://github.com/Vincamok/goproxify/raw/public/main/.env.example
$ cp .env.example .env
 
# 2. Fill secrets — or: bash quickstart.sh --env-only
$ # GPX_JWT_SECRET=$(openssl rand -hex 32)
$ # GPX_PAIRING_SECRET=$(openssl rand -hex 32)
 
# 3. Start Admin + Core + Agent
$ docker compose -f docker-compose.quickstart.yml up -d
 
# Admin UI → http://localhost:9443
.env (excerpt)
# Click the key icon to generate secrets in your browser
# Images (defaults = GHCR :preview)
# GOPROXIFY_ADMIN_TAG=preview
# GOPROXIFY_CORE_TAG=preview
# GOPROXIFY_AGENT_TAG=preview
# Required
GPX_JWT_SECRET=
GPX_PAIRING_SECRET=
GPX_FIRST_ADMIN_EMAIL=admin@example.com
GPX_FIRST_ADMIN_PASSWORD=

ADMIN_PORT=9443
Stacks → Add stack → Web editor. Pick a model, paste the compose, deploy. Admin on port 9443.

Paste the compose, then load stack.env (Advanced → Load variables from .env file) or set the same keys in Environment variables.

docker-compose.yml
# Portainer — model A: secrets via stack.env
networks:
  goproxify_net:
    name: goproxify_net

volumes:
  goproxify_admin_data:
  goproxify_core_data:
  goproxify_agent_data:

services:
  goproxify-admin:
    image: ghcr.io/vincamok/goproxify/admin:preview
    container_name: goproxify-admin
    restart: unless-stopped
    command: ["admin"]
    environment:
      - TZ=${TZ:-Europe/Paris}
      - GPX_SECURITY_JWT_SECRET=${GPX_JWT_SECRET}
      - GPX_PAIRING_SECRET=${GPX_PAIRING_SECRET}
      - GPX_FIRST_ADMIN_EMAIL=${GPX_FIRST_ADMIN_EMAIL}
      - GPX_FIRST_ADMIN_PASSWORD=${GPX_FIRST_ADMIN_PASSWORD}
      - GPX_IDENTITY_CORE_NODE_NAME=${CORE_NODE_NAME:-goproxify-core}
      - GPX_SERVER_API_PORT=9443
    ports:
      - "${ADMIN_PORT:-9443}:9443"
    volumes:
      - goproxify_admin_data:/etc/goproxify
    networks: [goproxify_net]

  goproxify-core:
    image: ghcr.io/vincamok/goproxify/core:preview
    container_name: goproxify-core
    restart: unless-stopped
    command: ["core"]
    environment:
      - TZ=${TZ:-Europe/Paris}
      - GPX_PAIRING_SECRET=${GPX_PAIRING_SECRET}
      - GPX_IDENTITY_CORE_NODE_NAME=${CORE_NODE_NAME:-goproxify-core}
    ports:
      - "${CORE_HTTP_PORT:-80}:80"
      - "${CORE_HTTPS_PORT:-443}:443"
      - "${CORE_HTTPS_PORT:-443}:443/udp"
    volumes:
      - goproxify_core_data:/etc/goproxify
    networks: [goproxify_net]
    depends_on: [goproxify-admin]

  goproxify-agent:
    image: ghcr.io/vincamok/goproxify/agent:preview
    container_name: goproxify-agent
    restart: unless-stopped
    command: ["agent"]
    environment:
      - TZ=${TZ:-Europe/Paris}
      - GPX_PAIRING_SECRET=${GPX_PAIRING_SECRET}
      - GPX_CONTROL_PLANE_CORE_ENDPOINT=http://goproxify-core:8000
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - goproxify_agent_data:/etc/goproxify
    networks: [goproxify_net]
    depends_on: [goproxify-core]
stack.env
# Click the key icon to generate secrets in your browser
# Nothing is sent to any server
GPX_JWT_SECRET=
GPX_PAIRING_SECRET=
GPX_FIRST_ADMIN_EMAIL=admin@example.com
GPX_FIRST_ADMIN_PASSWORD=
ADMIN_PORT=9443
TZ=Europe/Paris
CORE_NODE_NAME=goproxify-core

Single paste: replace CHANGE_ME_* before Deploy. No stack.env / env file needed.

docker-compose.yml
# Portainer — model B: inline secrets (no stack.env)
# Click the key icon to fill CHANGE_ME_* in your browser
networks:
  goproxify_net:
    name: goproxify_net

volumes:
  goproxify_admin_data:
  goproxify_core_data:
  goproxify_agent_data:

services:
  goproxify-admin:
    image: ghcr.io/vincamok/goproxify/admin:preview
    container_name: goproxify-admin
    restart: unless-stopped
    command: ["admin"]
    environment:
      - TZ=Europe/Paris
      - GPX_SECURITY_JWT_SECRET=CHANGE_ME_JWT_HEX32
      - GPX_PAIRING_SECRET=CHANGE_ME_PAIRING_HEX32
      - GPX_FIRST_ADMIN_EMAIL=admin@example.com
      - GPX_FIRST_ADMIN_PASSWORD=CHANGE_ME_PASSWORD_MIN12
      - GPX_IDENTITY_CORE_NODE_NAME=goproxify-core
      - GPX_SERVER_API_PORT=9443
    ports:
      - "9443:9443"
    volumes:
      - goproxify_admin_data:/etc/goproxify
    networks: [goproxify_net]

  goproxify-core:
    image: ghcr.io/vincamok/goproxify/core:preview
    container_name: goproxify-core
    restart: unless-stopped
    command: ["core"]
    environment:
      - TZ=Europe/Paris
      - GPX_PAIRING_SECRET=CHANGE_ME_PAIRING_HEX32
      - GPX_IDENTITY_CORE_NODE_NAME=goproxify-core
    ports:
      - "80:80"
      - "443:443"
      - "443:443/udp"
    volumes:
      - goproxify_core_data:/etc/goproxify
    networks: [goproxify_net]
    depends_on: [goproxify-admin]

  goproxify-agent:
    image: ghcr.io/vincamok/goproxify/agent:preview
    container_name: goproxify-agent
    restart: unless-stopped
    command: ["agent"]
    environment:
      - TZ=Europe/Paris
      - GPX_PAIRING_SECRET=CHANGE_ME_PAIRING_HEX32
      - GPX_CONTROL_PLANE_CORE_ENDPOINT=http://goproxify-core:8000
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - goproxify_agent_data:/etc/goproxify
    networks: [goproxify_net]
    depends_on: [goproxify-core]
Core and Agent pair via the same GPX_PAIRING_SECRET. Secrets are generated in your browser only — nothing is sent to any server.

Chart in the repo (helm/goproxify). Requires global.authToken. Generate secrets in your browser, then helm install.

values-secrets.yaml
# Click the key icon — secrets stay in your browser
fullnameOverride: goproxify

global:
  authToken: ""
  timezone: Europe/Paris

admin:
  image:
    tag: "preview"
  config:
    jwtSecret: ""
  ingress:
    enabled: true
    host: admin.example.com

core:
  image:
    tag: "preview"

agent:
  image:
    tag: "preview"
shell
# 1. Clone chart (public/main)
$ git clone -b public/main https://github.com/Vincamok/goproxify.git && cd goproxify
 
# 2. Save values-secrets.yaml (from the block above), then install
$ helm upgrade --install goproxify ./helm/goproxify \
-n goproxify --create-namespace \
-f values-secrets.yaml
 
# Admin Service → port-forward or Ingress host
$ kubectl -n goproxify port-forward svc/goproxify-admin 8080:8080
shell
# Build from source (Go 1.25+)
$ git clone -b public/main https://github.com/Vincamok/goproxify.git && cd goproxify
$ go build -o goproxify ./cmd/goproxify
 
# Click the key icon to fill secrets (browser-only)
# Admin (control plane)
$ GPX_SECURITY_JWT_SECRET=CHANGE_ME_JWT_HEX32 \
GPX_PAIRING_SECRET=CHANGE_ME_PAIRING_HEX32 \
./goproxify admin
 
# Core (data plane) — same pairing secret
$ GPX_PAIRING_SECRET=CHANGE_ME_PAIRING_HEX32 \
GPX_IDENTITY_CORE_NODE_NAME=goproxify-core \
./goproxify core
 
# Agent (optional)
$ GPX_PAIRING_SECRET=CHANGE_ME_PAIRING_HEX32 \
GPX_CONTROL_PLANE_CORE_ENDPOINT=http://localhost:8000 \
./goproxify agent

10 alert channels

Each alert rule can notify multiple teams on multiple channels at once. Alertmanager-inspired model.

Email

SMTP configurable

Webhook

Slack, Discord, Teams…

ntfy.sh

Push mobile, self-hosted

Gotify

Push mobile, self-hosted

Jira

Création d'issue auto

Linear

Issue tracking moderne

GitHub Issues

Ouverture d'issue

GitLab Issues

Ouverture d'issue

Zammad

Ticketing open-source

GLPI

ITSM, API REST

Tech stack

Deliberate choices. No heavy framework, no hidden runtime — just Go and proven libraries.

Component Role Used in
Go 1.25
Single static binary, zero runtime to install, native cross-compilation Admin · Core · Agent
HTTP/3 QUIC
UDP transport via quic-go. Automatic Alt-Svc, 0-RTT, lower latency on degraded networks Core
SQLite (CGO-free)
Persistance without C deps. Cross-platform binary. Optional Raft cluster (3 nodes) for Admin HA Admin
WebSocket control plane
Persistent Admin↔Core and Agent↔Core tunnels. full_sync, live metrics for adaptive LB, inter-Core gateway Admin · Core · Agent
Cache AES-256-GCM
Encrypted routes & certs on disk. Core starts autonomously even if Admin is unreachable Core
Prometheus
/metrics endpoint on every component — drop-in Grafana integration Admin · Core · Agent
OpenTelemetry
Distributed request tracing. Configurable OTLP exporters (Jaeger, Tempo…) Core · Admin
Docker Engine API
Read-only via docker.sock. Real-time container events (start/stop/update) Agent
JWT + PAT
UI session (JWT). User API tokens gpx_pat_* with scopes for REST & MCP. Separate Core/Agent pairing tokens Admin
MCP
Model Context Protocol (JSON-RPC + SSE). Proxies, nodes, logs, audit tools… PAT required — Claude Desktop / Cursor ready Admin
ACME DNS-01
Automatic wildcard certs via OVH, Cloudflare, Gandi, Route53, Hetzner Admin → Core

Documentation

Guides, API contract, MCP server and version tracking — all in the repo.