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

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 pieces work together — here is what each one does for you day to day.

Admin

Your control panel

A clear web interface to run the whole setup: publish sites, attach domain names, invite teammates, schedule backups, and follow alerts — in your language (EN, FR, ES, DE).

  • Create and edit which address opens which site
  • Manage domains and certificates from one place
  • Team access, backups and alerts without touching config files
Gateway

The traffic gateways

Gateways are the public front door. They welcome visitors on your https://… addresses and send each one to the right site in your fleet — quietly, and at scale.

  • Expose several websites behind their own internet addresses
  • Share load when several copies of an app are running
  • Keep traffic flowing if you run more than one gateway
Agent + Portainer

Your container fleet, connected

The Agent watches your containers (via Portainer or Docker) and tells the gateways what is running. When you start, stop or move an app, public routes stay in sync.

  • Discover new containers as they appear
  • Stay linked to Portainer to manage the whole fleet
  • Update routes automatically when apps change
Reliability

Keeps working when things break

Your sites should not go dark because one machine hiccups. Gateways remember their settings, a spare gateway can take over, and unhealthy apps are skipped.

  • Sites keep answering even if the Admin is briefly offline
  • A second gateway covers for the first
  • Failing apps are bypassed so visitors still reach a healthy copy
Security

Protect what you publish

Putting sites on the internet invites bots and abuse. GoProxify helps you slow attacks, block threats, and ask for a login when a site should stay private.

  • Limit abusive traffic and suspicious visitors
  • Block known threats before they reach your apps
  • Require a login for sensitive tools and internal apps
Visibility

See what happens

Know who visits which site, spot errors quickly, and get notified where your team already works — without digging through server files.

  • Live views of traffic across your published sites
  • Clear access logs you can actually read
  • Alerts on several channels when something goes wrong
Access

Reach servers from the browser

When an operator needs a shell on a VM or container, they open a secure terminal in the browser. You invite people, set limits, and avoid sharing passwords in chat.

  • Secure web terminal to VMs and containers
  • Invite operators with the access they need — no more
  • Optional second factor instead of shared passwords

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.