mirror of
https://github.com/mcloh/codex-chatgpt-mcp-proxy.git
synced 2026-11-05 21:34:11 +00:00
Implement durable OAuth MCP bridge with local Codex worker and deployment guides
This commit is contained in:
4
deploy/base-images.json
Normal file
4
deploy/base-images.json
Normal file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"python:3.12-slim-bookworm": "python@sha256:34386ef0cb081344d7ec1c103ba398e6e9f64e9ab3a1509accc92a4e24a07258",
|
||||
"nginx:1.28-alpine": "nginx@sha256:a8b39bd9cf0f83869a2162827a0caf6137ddf759d50a171451b335cecc87d236"
|
||||
}
|
||||
19
deploy/codex-bridge-worker.service.example
Normal file
19
deploy/codex-bridge-worker.service.example
Normal file
@@ -0,0 +1,19 @@
|
||||
[Unit]
|
||||
Description=Codex outbound MCP bridge worker
|
||||
After=network-online.target
|
||||
Wants=network-online.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
WorkingDirectory=/absolute/path/to/repository
|
||||
EnvironmentFile=/absolute/path/to/private/worker.env
|
||||
ExecStart=/absolute/path/to/repository/.venv/bin/codex-bridge worker
|
||||
Restart=on-failure
|
||||
RestartSec=10
|
||||
TimeoutStopSec=45
|
||||
UMask=0077
|
||||
# Do not add NoNewPrivileges here without testing: it can interfere with Codex's sandbox.
|
||||
# This is a user unit. All approval decisions remain local.
|
||||
|
||||
[Install]
|
||||
WantedBy=default.target
|
||||
36
deploy/keycloak-nginx.conf.template
Normal file
36
deploy/keycloak-nginx.conf.template
Normal file
@@ -0,0 +1,36 @@
|
||||
pid /tmp/nginx.pid;
|
||||
error_log /dev/stderr warn;
|
||||
events { worker_connections 128; }
|
||||
http {
|
||||
access_log off;
|
||||
client_body_temp_path /tmp/client_body;
|
||||
proxy_temp_path /tmp/proxy_temp;
|
||||
fastcgi_temp_path /tmp/fastcgi_temp;
|
||||
uwsgi_temp_path /tmp/uwsgi_temp;
|
||||
scgi_temp_path /tmp/scgi_temp;
|
||||
server {
|
||||
listen 8080;
|
||||
server_name ${BRIDGE_PUBLIC_HOST};
|
||||
client_max_body_size 128k;
|
||||
location = /.well-known/oauth-authorization-server/realms/codex-bridge {
|
||||
proxy_pass ${BRIDGE_KEYCLOAK_UPSTREAM}/realms/codex-bridge/.well-known/openid-configuration;
|
||||
proxy_set_header Host ${BRIDGE_PUBLIC_HOST};
|
||||
proxy_set_header X-Forwarded-Host ${BRIDGE_PUBLIC_HOST};
|
||||
proxy_set_header X-Forwarded-Proto https;
|
||||
proxy_set_header X-Forwarded-Port 443;
|
||||
}
|
||||
location /realms/codex-bridge/ {
|
||||
proxy_pass ${BRIDGE_KEYCLOAK_UPSTREAM};
|
||||
proxy_set_header Host ${BRIDGE_PUBLIC_HOST};
|
||||
proxy_set_header X-Forwarded-Host ${BRIDGE_PUBLIC_HOST};
|
||||
proxy_set_header X-Forwarded-Proto https;
|
||||
proxy_set_header X-Forwarded-Port 443;
|
||||
}
|
||||
location /resources/ {
|
||||
proxy_pass ${BRIDGE_KEYCLOAK_UPSTREAM};
|
||||
proxy_set_header Host ${BRIDGE_PUBLIC_HOST};
|
||||
proxy_set_header X-Forwarded-Proto https;
|
||||
}
|
||||
location / { return 404; }
|
||||
}
|
||||
}
|
||||
32
deploy/keycloak.compose.yaml
Normal file
32
deploy/keycloak.compose.yaml
Normal file
@@ -0,0 +1,32 @@
|
||||
# Optional routing for an EXISTING Keycloak on the existing proxy network.
|
||||
# No Keycloak restart, credentials or Docker socket required by this container.
|
||||
services:
|
||||
identity-route:
|
||||
image: ${BRIDGE_NGINX_IMAGE:?Set a verified Nginx image digest}
|
||||
user: "101:101"
|
||||
entrypoint: ["/bin/sh", "-c"]
|
||||
command:
|
||||
- 'envsubst ''$${BRIDGE_KEYCLOAK_UPSTREAM} $${BRIDGE_PUBLIC_HOST}'' < /etc/bridge/nginx.conf.template > /tmp/nginx.conf && exec nginx -c /tmp/nginx.conf -g ''daemon off;'''
|
||||
environment:
|
||||
BRIDGE_KEYCLOAK_UPSTREAM: ${BRIDGE_KEYCLOAK_UPSTREAM:?Set existing Keycloak internal URL}
|
||||
BRIDGE_PUBLIC_HOST: ${BRIDGE_PUBLIC_HOST}
|
||||
volumes:
|
||||
- ./deploy/keycloak-nginx.conf.template:/etc/bridge/nginx.conf.template:ro
|
||||
networks:
|
||||
- proxy
|
||||
restart: unless-stopped
|
||||
read_only: true
|
||||
tmpfs:
|
||||
- /tmp:size=32M,mode=1777
|
||||
cap_drop: [ALL]
|
||||
security_opt: [no-new-privileges:true]
|
||||
mem_limit: 64m
|
||||
pids_limit: 32
|
||||
labels:
|
||||
traefik.enable: "true"
|
||||
traefik.docker.network: ${BRIDGE_PROXY_NETWORK}
|
||||
traefik.http.routers.codex-bridge-identity.rule: Host(`${BRIDGE_PUBLIC_HOST}`) && (PathPrefix(`/realms/codex-bridge/`) || PathPrefix(`/resources/`) || Path(`/.well-known/oauth-authorization-server/realms/codex-bridge`))
|
||||
traefik.http.routers.codex-bridge-identity.entrypoints: ${BRIDGE_PROXY_ENTRYPOINT:-websecure}
|
||||
traefik.http.routers.codex-bridge-identity.tls: "true"
|
||||
traefik.http.routers.codex-bridge-identity.tls.certresolver: ${BRIDGE_TLS_RESOLVER}
|
||||
traefik.http.services.codex-bridge-identity.loadbalancer.server.port: "8080"
|
||||
12
deploy/nginx-location.conf.example
Normal file
12
deploy/nginx-location.conf.example
Normal file
@@ -0,0 +1,12 @@
|
||||
# Optional alternative for an existing Nginx proxy. Inspect existing config first.
|
||||
# Inside an existing TLS vhost whose server_name comes from deployment configuration:
|
||||
location / {
|
||||
proxy_pass http://codex-bridge:8000;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Forwarded-Proto https;
|
||||
proxy_set_header X-Forwarded-For $remote_addr;
|
||||
proxy_http_version 1.1;
|
||||
proxy_buffering off;
|
||||
proxy_read_timeout 90s;
|
||||
}
|
||||
# The app ignores forwarded headers entirely; it uses BRIDGE_PUBLIC_URL for metadata.
|
||||
Reference in New Issue
Block a user