Merge changemaker-control-panel into v2 monorepo

Absorbs the separate control-panel git repo as a subdirectory.
Instances and backups directories excluded via .gitignore.

Bunker Admin
This commit is contained in:
2026-02-21 11:51:45 -07:00
parent 7352815e57
commit 2fa50b001c
80 changed files with 16513 additions and 1 deletions

View File

@@ -0,0 +1,2 @@
# API-specific configuration placeholder
# (Primary API routing is in default.conf)

View File

@@ -0,0 +1,81 @@
# Changemaker Lite Nginx — Instance: {{name}}
# Routes all traffic through single entry point
server {
listen 80 default_server;
server_name localhost _;
add_header X-Frame-Options "SAMEORIGIN" always;
# Admin GUI + Public pages (default)
location / {
set $upstream_admin http://{{containerPrefix}}-admin:3000;
proxy_pass $upstream_admin;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
{{#if enableMedia}}
# Media API admin routes (must come BEFORE /api/ for longest prefix match)
# Rewrites /api/media/* to /api/* on media-api
location /api/media/ {
set $upstream_media http://{{containerPrefix}}-media-api:4100;
rewrite ^/api/media/(.*) /api/$1 break;
proxy_pass $upstream_media;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# Large upload support
client_max_body_size 10G;
proxy_read_timeout 3600s;
proxy_connect_timeout 75s;
proxy_request_buffering off;
# WebSocket support
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
# Media API routes rewrite (matches Vite dev proxy behavior)
# Rewrites /media/* to /api/* on media-api (port 4100)
location /media/ {
set $upstream_media_default http://{{containerPrefix}}-media-api:4100;
rewrite ^/media/(.*) /api/$1 break;
proxy_pass $upstream_media_default;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# Large upload support
client_max_body_size 10G;
proxy_read_timeout 3600s;
proxy_connect_timeout 75s;
proxy_request_buffering off;
# WebSocket support
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
{{/if}}
# Express API
location /api/ {
set $upstream_api http://{{containerPrefix}}-api:4000;
proxy_pass $upstream_api;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 3600s;
}
}

View File

@@ -0,0 +1,243 @@
# Changemaker Lite — Instance: {{name}}
# Embed proxy ports for iframe embedding in admin GUI.
# These strip X-Frame-Options and CSP so services can be iframed.
# Internal ports 8881-8894 are mapped to host ports via docker-compose.
# NocoDB embed proxy (internal 8881)
server {
listen 8881;
location / {
set $upstream_nocodb http://{{containerPrefix}}-nocodb:8080;
proxy_pass $upstream_nocodb;
proxy_hide_header X-Frame-Options;
proxy_hide_header Content-Security-Policy;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
# n8n embed proxy (internal 8882)
server {
listen 8882;
location / {
set $upstream_n8n http://{{containerPrefix}}-n8n:5678;
proxy_pass $upstream_n8n;
proxy_hide_header X-Frame-Options;
proxy_hide_header Content-Security-Policy;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
# Gitea embed proxy (internal 8883)
server {
listen 8883;
client_max_body_size 2048M;
location / {
set $upstream_gitea http://{{containerPrefix}}-gitea:3000;
proxy_pass $upstream_gitea;
proxy_hide_header X-Frame-Options;
proxy_hide_header Content-Security-Policy;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
# MailHog embed proxy (internal 8884)
server {
listen 8884;
location / {
set $upstream_mailhog http://{{containerPrefix}}-mailhog:8025;
proxy_pass $upstream_mailhog;
proxy_hide_header X-Frame-Options;
proxy_hide_header Content-Security-Policy;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
# Mini QR embed proxy (internal 8885)
server {
listen 8885;
location / {
set $upstream_miniqr http://{{containerPrefix}}-mini-qr:8080;
proxy_pass $upstream_miniqr;
proxy_hide_header X-Frame-Options;
proxy_hide_header Content-Security-Policy;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
# Excalidraw embed proxy (internal 8886)
server {
listen 8886;
location / {
set $upstream_excalidraw http://{{containerPrefix}}-excalidraw:80;
proxy_pass $upstream_excalidraw;
proxy_hide_header X-Frame-Options;
proxy_hide_header Content-Security-Policy;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_http_version 1.1;
}
}
# Homepage embed proxy (internal 8887)
server {
listen 8887;
location / {
set $upstream_homepage http://{{containerPrefix}}-homepage:3000;
proxy_pass $upstream_homepage;
proxy_hide_header X-Frame-Options;
proxy_hide_header Content-Security-Policy;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
# Code Server embed proxy (internal 8888)
server {
listen 8888;
location / {
set $upstream_code http://{{containerPrefix}}-code-server:8080;
proxy_pass $upstream_code;
proxy_hide_header X-Frame-Options;
proxy_hide_header Content-Security-Policy;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
# MkDocs embed proxy (internal 8889)
server {
listen 8889;
location / {
set $upstream_mkdocs http://{{containerPrefix}}-mkdocs:8000;
proxy_pass $upstream_mkdocs;
proxy_hide_header X-Frame-Options;
proxy_hide_header Content-Security-Policy;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
# Vaultwarden embed proxy (internal 8890)
server {
listen 8890;
location / {
set $upstream_vaultwarden http://{{containerPrefix}}-vaultwarden:80;
proxy_pass $upstream_vaultwarden;
proxy_hide_header X-Frame-Options;
proxy_hide_header Content-Security-Policy;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_http_version 1.1;
}
}
# Rocket.Chat embed proxy (internal 8891)
{{#if enableChat}}
server {
listen 8891;
location / {
set $upstream_rocketchat http://{{containerPrefix}}-rocketchat:3000;
proxy_pass $upstream_rocketchat;
proxy_hide_header X-Frame-Options;
proxy_hide_header Content-Security-Policy;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_http_version 1.1;
client_max_body_size 100m;
}
}
{{/if}}
# Gancio embed proxy (internal 8892)
{{#if enableGancio}}
server {
listen 8892;
location / {
set $upstream_gancio http://{{containerPrefix}}-gancio:13120;
proxy_pass $upstream_gancio;
proxy_hide_header X-Frame-Options;
proxy_hide_header Content-Security-Policy;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
{{/if}}
# Grafana embed proxy (internal 8893)
{{#if enableMonitoring}}
server {
listen 8893;
location / {
set $upstream_grafana http://{{containerPrefix}}-grafana:3000;
proxy_pass $upstream_grafana;
proxy_hide_header X-Frame-Options;
proxy_hide_header Content-Security-Policy;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
{{/if}}
# Listmonk embed proxy (internal 8894)
{{#if enableListmonk}}
server {
listen 8894;
location / {
set $upstream_listmonk http://{{containerPrefix}}-listmonk:9000;
proxy_pass $upstream_listmonk;
proxy_hide_header X-Frame-Options;
proxy_hide_header Content-Security-Policy;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
{{/if}}

View File

@@ -0,0 +1,47 @@
worker_processes auto;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
server_tokens off;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
client_max_body_size 50m;
# Gzip compression
gzip on;
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript image/svg+xml;
# Security headers (applied globally — X-Frame-Options set per server block)
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
add_header Permissions-Policy "geolocation=(self), microphone=(), camera=()" always;
# Docker internal DNS — enables runtime resolution so nginx starts
# even when optional services are not running
resolver 127.0.0.11 valid=30s;
include /etc/nginx/conf.d/*.conf;
}