feat: added proxy and admin entrypoint
This commit is contained in:
+55
-13
@@ -189,6 +189,7 @@ services:
|
|||||||
- type: volume
|
- type: volume
|
||||||
source: redis_data
|
source: redis_data
|
||||||
target: /data
|
target: /data
|
||||||
|
read_only: false
|
||||||
|
|
||||||
redis-exporter:
|
redis-exporter:
|
||||||
image: docker.io/oliver006/redis_exporter:v1.74.0-alpine
|
image: docker.io/oliver006/redis_exporter:v1.74.0-alpine
|
||||||
@@ -226,14 +227,12 @@ services:
|
|||||||
retries: 5
|
retries: 5
|
||||||
oom_kill_disable: true
|
oom_kill_disable: true
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
secrets:
|
|
||||||
- source: postgres_password
|
|
||||||
target: /run/secrets/postgres_password
|
|
||||||
shm_size: 128mb
|
shm_size: 128mb
|
||||||
volumes:
|
volumes:
|
||||||
- type: volume
|
- type: volume
|
||||||
source: postgres_data
|
source: postgres_data
|
||||||
target: /var/lib/postgresql/data
|
target: /var/lib/postgresql/data
|
||||||
|
read_only: false
|
||||||
|
|
||||||
postgres-exporter:
|
postgres-exporter:
|
||||||
image: quay.io/prometheuscommunity/postgres-exporter:v0.17.1
|
image: quay.io/prometheuscommunity/postgres-exporter:v0.17.1
|
||||||
@@ -253,7 +252,7 @@ services:
|
|||||||
shm_size: 4mb
|
shm_size: 4mb
|
||||||
|
|
||||||
pgadmin:
|
pgadmin:
|
||||||
image: docker.io/dpage/pgadmin4:9.5
|
image: docker.io/dpage/pgadmin4:9.6
|
||||||
configs:
|
configs:
|
||||||
- source: pgadmin_servers_config
|
- source: pgadmin_servers_config
|
||||||
target: /pgadmin4/servers.json
|
target: /pgadmin4/servers.json
|
||||||
@@ -284,14 +283,12 @@ services:
|
|||||||
profiles:
|
profiles:
|
||||||
- observability
|
- observability
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
secrets:
|
|
||||||
- source: pgadmin_password
|
|
||||||
target: /run/secrets/pgadmin_password
|
|
||||||
shm_size: 4mb
|
shm_size: 4mb
|
||||||
volumes:
|
volumes:
|
||||||
- type: volume
|
- type: volume
|
||||||
source: pgadmin_data
|
source: pgadmin_data
|
||||||
target: /var/lib/pgadmin
|
target: /var/lib/pgadmin
|
||||||
|
read_only: false
|
||||||
|
|
||||||
grafana:
|
grafana:
|
||||||
image: docker.io/grafana/grafana-oss:12.0.2
|
image: docker.io/grafana/grafana-oss:12.0.2
|
||||||
@@ -321,12 +318,15 @@ services:
|
|||||||
- type: volume
|
- type: volume
|
||||||
source: grafana_data
|
source: grafana_data
|
||||||
target: /var/lib/grafana
|
target: /var/lib/grafana
|
||||||
|
read_only: false
|
||||||
- type: bind
|
- type: bind
|
||||||
source: ./infrastructure/grafana/provisioning
|
source: ./infrastructure/grafana/provisioning
|
||||||
target: /etc/grafana/provisioning
|
target: /etc/grafana/provisioning
|
||||||
|
read_only: true
|
||||||
- type: bind
|
- type: bind
|
||||||
source: ./infrastructure/grafana/scripts
|
source: ./infrastructure/grafana/scripts
|
||||||
target: /etc/grafana/scripts
|
target: /etc/grafana/scripts
|
||||||
|
read_only: true
|
||||||
|
|
||||||
prometheus:
|
prometheus:
|
||||||
image: docker.io/prom/prometheus:v3.5.0
|
image: docker.io/prom/prometheus:v3.5.0
|
||||||
@@ -356,6 +356,7 @@ services:
|
|||||||
- type: volume
|
- type: volume
|
||||||
source: prometheus_data
|
source: prometheus_data
|
||||||
target: /prometheus
|
target: /prometheus
|
||||||
|
read_only: false
|
||||||
|
|
||||||
minio:
|
minio:
|
||||||
image: docker.io/minio/minio:RELEASE.2025-07-18T21-56-31Z
|
image: docker.io/minio/minio:RELEASE.2025-07-18T21-56-31Z
|
||||||
@@ -393,6 +394,7 @@ services:
|
|||||||
- type: volume
|
- type: volume
|
||||||
source: minio_data
|
source: minio_data
|
||||||
target: /data
|
target: /data
|
||||||
|
read_only: false
|
||||||
|
|
||||||
zipkin:
|
zipkin:
|
||||||
image: docker.io/openzipkin/zipkin:3
|
image: docker.io/openzipkin/zipkin:3
|
||||||
@@ -443,6 +445,48 @@ services:
|
|||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
shm_size: 4mb
|
shm_size: 4mb
|
||||||
|
|
||||||
|
proxy:
|
||||||
|
image: docker.io/caddy:2-alpine
|
||||||
|
configs:
|
||||||
|
- source: caddy_config
|
||||||
|
target: /etc/caddy/Caddyfile
|
||||||
|
ports:
|
||||||
|
- name: http
|
||||||
|
target: 80
|
||||||
|
published: 80
|
||||||
|
host_ip: 0.0.0.0
|
||||||
|
protocol: tcp
|
||||||
|
app_protocol: http
|
||||||
|
- name: https
|
||||||
|
target: 443
|
||||||
|
published: 443
|
||||||
|
host_ip: 0.0.0.0
|
||||||
|
protocol: tcp
|
||||||
|
app_protocol: http
|
||||||
|
- name: http3
|
||||||
|
target: 443
|
||||||
|
published: 443
|
||||||
|
host_ip: 0.0.0.0
|
||||||
|
protocol: udp
|
||||||
|
app_protocol: http
|
||||||
|
profiles:
|
||||||
|
- proxy
|
||||||
|
restart: unless-stopped
|
||||||
|
shm_size: 4mb
|
||||||
|
volumes:
|
||||||
|
- type: volume
|
||||||
|
source: caddy_data
|
||||||
|
target: /data
|
||||||
|
read_only: false
|
||||||
|
- type: volume
|
||||||
|
source: caddy_config
|
||||||
|
target: /config
|
||||||
|
read_only: false
|
||||||
|
- type: bind
|
||||||
|
source: ./infrastructure/caddy/static
|
||||||
|
target: /var/www
|
||||||
|
read_only: true
|
||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
redis_data:
|
redis_data:
|
||||||
postgres_data:
|
postgres_data:
|
||||||
@@ -450,6 +494,8 @@ volumes:
|
|||||||
grafana_data:
|
grafana_data:
|
||||||
prometheus_data:
|
prometheus_data:
|
||||||
minio_data:
|
minio_data:
|
||||||
|
caddy_data:
|
||||||
|
caddy_config:
|
||||||
|
|
||||||
configs:
|
configs:
|
||||||
redis_config:
|
redis_config:
|
||||||
@@ -462,9 +508,5 @@ configs:
|
|||||||
file: ./infrastructure/grafana/grafana.ini
|
file: ./infrastructure/grafana/grafana.ini
|
||||||
prometheus_config:
|
prometheus_config:
|
||||||
file: ./infrastructure/prometheus/prometheus.yaml
|
file: ./infrastructure/prometheus/prometheus.yaml
|
||||||
|
caddy_config:
|
||||||
secrets:
|
file: ./infrastructure/caddy/Caddyfile
|
||||||
postgres_password:
|
|
||||||
file: ./infrastructure/postgres/password
|
|
||||||
pgadmin_password:
|
|
||||||
file: ./infrastructure/pgadmin/password
|
|
||||||
|
|||||||
@@ -0,0 +1,29 @@
|
|||||||
|
(basic-auth) {
|
||||||
|
basic_auth {
|
||||||
|
admin $2a$14$2zQilpLka2h8Sn1mmOLAAezwDN8Zy8Ta36WECk4qt5MTn3CWksR0m
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
adnova.itqdev.xyz {
|
||||||
|
handle_path /health/* {
|
||||||
|
import basic-auth
|
||||||
|
}
|
||||||
|
|
||||||
|
reverse_proxy http://backend:8080
|
||||||
|
}
|
||||||
|
|
||||||
|
admin.adnova.itqdev.xyz {
|
||||||
|
import basic-auth
|
||||||
|
|
||||||
|
root * /var/www/admin
|
||||||
|
}
|
||||||
|
|
||||||
|
loadtest.adnova.itqdev.xyz {
|
||||||
|
import basic-auth
|
||||||
|
|
||||||
|
reverse_proxy http://loadtest:5001
|
||||||
|
}
|
||||||
|
|
||||||
|
grafana.adnova.itqdev.xyz {
|
||||||
|
reverse_proxy http://grafana:3000
|
||||||
|
}
|
||||||
@@ -0,0 +1,198 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en" class="dark">
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>AdNova Admin Resources</title>
|
||||||
|
<script src="https://cdn.tailwindcss.com"></script>
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
font-family: 'Inter', sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap');
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body class="bg-slate-900 text-gray-300">
|
||||||
|
<div class="container mx-auto p-4 md:p-8">
|
||||||
|
<header class="mb-8">
|
||||||
|
<h1 class="text-4xl font-bold text-white tracking-tight">AdNova Admin Resources Dashboard</h1>
|
||||||
|
<p class="text-indigo-400">Quick access to essential tools and credentials.</p>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<div id="resources-container" class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
const resources = [
|
||||||
|
{
|
||||||
|
category: "Development Tools",
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
name: "Gitea Repository",
|
||||||
|
link: "https://git.itqdev.xyz/PROD.2025/AdNova",
|
||||||
|
description: "Main monorepo."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Jira Project Board",
|
||||||
|
link: "https://jira.example.com/project",
|
||||||
|
description: "Task tracking and project management."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Jenkins CI/CD",
|
||||||
|
link: "https://jenkins.example.com",
|
||||||
|
username: "ci_admin",
|
||||||
|
password: "jenkins_pass",
|
||||||
|
description: "Continuous Integration and Deployment pipelines."
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
category: "Cloud Platforms",
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
name: "AWS Console",
|
||||||
|
link: "https://console.aws.amazon.com",
|
||||||
|
username: "aws_root",
|
||||||
|
password: "aws_super_secret",
|
||||||
|
description: "Access to AWS cloud services."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Google Cloud Console",
|
||||||
|
link: "https://console.cloud.google.com",
|
||||||
|
description: "Access to Google Cloud Platform services."
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
category: "Monitoring",
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
name: "Grafana",
|
||||||
|
link: "https://grafana.example.com",
|
||||||
|
username: "admin",
|
||||||
|
password: "proooooood",
|
||||||
|
description: "Real-time system metrics and dashboards."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Kibana Logs",
|
||||||
|
link: "https://kibana.example.com",
|
||||||
|
description: "Centralized log management and analysis."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Adnova Alerts",
|
||||||
|
link: "https://t.me/adnova_alerts",
|
||||||
|
description: "Telegram channel where alerts are posted."
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
category: "Databases",
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
name: "Production DB Admin",
|
||||||
|
link: "https://dbadmin.example.com/prod",
|
||||||
|
username: "db_prod_admin",
|
||||||
|
password: "db_prod_secure_pass",
|
||||||
|
description: "Direct access to production database."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Staging DB Admin",
|
||||||
|
link: "https://dbadmin.example.com/staging",
|
||||||
|
username: "db_stage_user",
|
||||||
|
password: "db_stage_pass",
|
||||||
|
description: "Access to staging database for testing."
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
function copyToClipboard ( text )
|
||||||
|
{
|
||||||
|
const textarea = document.createElement( 'textarea' )
|
||||||
|
textarea.value = text
|
||||||
|
document.body.appendChild( textarea )
|
||||||
|
textarea.select()
|
||||||
|
document.execCommand( 'copy' )
|
||||||
|
document.body.removeChild( textarea )
|
||||||
|
alert( 'Copied to clipboard!' )
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderResources ()
|
||||||
|
{
|
||||||
|
const container = document.getElementById( 'resources-container' )
|
||||||
|
container.innerHTML = ''
|
||||||
|
|
||||||
|
resources.forEach( categoryData =>
|
||||||
|
{
|
||||||
|
const categorySection = document.createElement( 'div' )
|
||||||
|
categorySection.className = 'col-span-full mb-4'
|
||||||
|
categorySection.innerHTML = `
|
||||||
|
<h2 class="text-2xl font-semibold text-white mb-4 border-b border-slate-700 pb-2">
|
||||||
|
${ categoryData.category }
|
||||||
|
</h2>
|
||||||
|
`
|
||||||
|
container.appendChild( categorySection )
|
||||||
|
|
||||||
|
categoryData.items.forEach( resource =>
|
||||||
|
{
|
||||||
|
const resourceCard = document.createElement( 'div' )
|
||||||
|
resourceCard.className = 'bg-slate-800 rounded-lg p-6 shadow-lg flex flex-col justify-between'
|
||||||
|
|
||||||
|
let credentialsHtml = ''
|
||||||
|
if ( resource.username || resource.password )
|
||||||
|
{
|
||||||
|
credentialsHtml = `
|
||||||
|
<div class="mt-4 pt-4 border-t border-slate-700">
|
||||||
|
<h4 class="text-sm font-medium text-slate-400 mb-2">Credentials:</h4>
|
||||||
|
${ resource.username ? `
|
||||||
|
<div class="flex items-center text-sm mb-2">
|
||||||
|
<span class="font-semibold text-slate-300 w-24">Username:</span>
|
||||||
|
<span id="user-${ resource.name.replace( /\s/g, '' ) }" class="flex-grow text-white font-mono mr-2">${ resource.username }</span>
|
||||||
|
<button class="copy-btn bg-slate-700 hover:bg-slate-600 text-slate-300 text-xs px-2 py-1 rounded-md" data-text="${ resource.username }">Copy</button>
|
||||||
|
</div>` : '' }
|
||||||
|
${ resource.password ? `
|
||||||
|
<div class="flex items-center text-sm">
|
||||||
|
<span class="font-semibold text-slate-300 w-24">Password:</span>
|
||||||
|
<span id="pass-${ resource.name.replace( /\s/g, '' ) }" class="flex-grow text-white font-mono mr-2">${ resource.password }</span>
|
||||||
|
<button class="copy-btn bg-slate-700 hover:bg-slate-600 text-slate-300 text-xs px-2 py-1 rounded-md" data-text="${ resource.password }">Copy</button>
|
||||||
|
</div>` : '' }
|
||||||
|
</div>
|
||||||
|
`
|
||||||
|
}
|
||||||
|
|
||||||
|
resourceCard.innerHTML = `
|
||||||
|
<div>
|
||||||
|
<h3 class="text-xl font-semibold text-white mb-2">${ resource.name }</h3>
|
||||||
|
<p class="text-sm text-slate-400 mb-4">${ resource.description || 'No description provided.' }</p>
|
||||||
|
</div>
|
||||||
|
<div class="mt-auto">
|
||||||
|
<a href="${ resource.link }" target="_blank" class="inline-flex items-center justify-center bg-indigo-600 hover:bg-indigo-500 text-white font-bold py-2 px-4 rounded-lg transition-colors duration-300 text-sm">
|
||||||
|
Go to Resource
|
||||||
|
<svg class="ml-2 -mr-1 w-4 h-4" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path d="M11 3a1 1 0 100 2h2.586l-6.293 6.293a1 1 0 101.414 1.414L15 6.414V9a1 1 0 102 0V4a1 1 0 00-1-1h-5z"></path><path d="M5 5a2 2 0 00-2 2v8a2 2 0 002 2h8a2 2 0 002-2v-3a1 1 0 10-2 0v3H5V7h3a1 1 0 000-2H5z"></path></svg>
|
||||||
|
</a>
|
||||||
|
${ credentialsHtml }
|
||||||
|
</div>
|
||||||
|
`
|
||||||
|
container.appendChild( resourceCard )
|
||||||
|
} )
|
||||||
|
} )
|
||||||
|
|
||||||
|
document.querySelectorAll( '.copy-btn' ).forEach( button =>
|
||||||
|
{
|
||||||
|
button.addEventListener( 'click', ( event ) =>
|
||||||
|
{
|
||||||
|
const textToCopy = event.target.dataset.text
|
||||||
|
copyToClipboard( textToCopy )
|
||||||
|
} )
|
||||||
|
} )
|
||||||
|
}
|
||||||
|
|
||||||
|
window.onload = renderResources;
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
||||||
Reference in New Issue
Block a user