feat: added proxy and admin entrypoint
This commit is contained in:
+55
-13
@@ -189,6 +189,7 @@ services:
|
||||
- type: volume
|
||||
source: redis_data
|
||||
target: /data
|
||||
read_only: false
|
||||
|
||||
redis-exporter:
|
||||
image: docker.io/oliver006/redis_exporter:v1.74.0-alpine
|
||||
@@ -226,14 +227,12 @@ services:
|
||||
retries: 5
|
||||
oom_kill_disable: true
|
||||
restart: unless-stopped
|
||||
secrets:
|
||||
- source: postgres_password
|
||||
target: /run/secrets/postgres_password
|
||||
shm_size: 128mb
|
||||
volumes:
|
||||
- type: volume
|
||||
source: postgres_data
|
||||
target: /var/lib/postgresql/data
|
||||
read_only: false
|
||||
|
||||
postgres-exporter:
|
||||
image: quay.io/prometheuscommunity/postgres-exporter:v0.17.1
|
||||
@@ -253,7 +252,7 @@ services:
|
||||
shm_size: 4mb
|
||||
|
||||
pgadmin:
|
||||
image: docker.io/dpage/pgadmin4:9.5
|
||||
image: docker.io/dpage/pgadmin4:9.6
|
||||
configs:
|
||||
- source: pgadmin_servers_config
|
||||
target: /pgadmin4/servers.json
|
||||
@@ -284,14 +283,12 @@ services:
|
||||
profiles:
|
||||
- observability
|
||||
restart: unless-stopped
|
||||
secrets:
|
||||
- source: pgadmin_password
|
||||
target: /run/secrets/pgadmin_password
|
||||
shm_size: 4mb
|
||||
volumes:
|
||||
- type: volume
|
||||
source: pgadmin_data
|
||||
target: /var/lib/pgadmin
|
||||
read_only: false
|
||||
|
||||
grafana:
|
||||
image: docker.io/grafana/grafana-oss:12.0.2
|
||||
@@ -321,12 +318,15 @@ services:
|
||||
- type: volume
|
||||
source: grafana_data
|
||||
target: /var/lib/grafana
|
||||
read_only: false
|
||||
- type: bind
|
||||
source: ./infrastructure/grafana/provisioning
|
||||
target: /etc/grafana/provisioning
|
||||
read_only: true
|
||||
- type: bind
|
||||
source: ./infrastructure/grafana/scripts
|
||||
target: /etc/grafana/scripts
|
||||
read_only: true
|
||||
|
||||
prometheus:
|
||||
image: docker.io/prom/prometheus:v3.5.0
|
||||
@@ -356,6 +356,7 @@ services:
|
||||
- type: volume
|
||||
source: prometheus_data
|
||||
target: /prometheus
|
||||
read_only: false
|
||||
|
||||
minio:
|
||||
image: docker.io/minio/minio:RELEASE.2025-07-18T21-56-31Z
|
||||
@@ -393,6 +394,7 @@ services:
|
||||
- type: volume
|
||||
source: minio_data
|
||||
target: /data
|
||||
read_only: false
|
||||
|
||||
zipkin:
|
||||
image: docker.io/openzipkin/zipkin:3
|
||||
@@ -443,6 +445,48 @@ services:
|
||||
restart: unless-stopped
|
||||
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:
|
||||
redis_data:
|
||||
postgres_data:
|
||||
@@ -450,6 +494,8 @@ volumes:
|
||||
grafana_data:
|
||||
prometheus_data:
|
||||
minio_data:
|
||||
caddy_data:
|
||||
caddy_config:
|
||||
|
||||
configs:
|
||||
redis_config:
|
||||
@@ -462,9 +508,5 @@ configs:
|
||||
file: ./infrastructure/grafana/grafana.ini
|
||||
prometheus_config:
|
||||
file: ./infrastructure/prometheus/prometheus.yaml
|
||||
|
||||
secrets:
|
||||
postgres_password:
|
||||
file: ./infrastructure/postgres/password
|
||||
pgadmin_password:
|
||||
file: ./infrastructure/pgadmin/password
|
||||
caddy_config:
|
||||
file: ./infrastructure/caddy/Caddyfile
|
||||
|
||||
@@ -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