forked from Nixius/authelia
Compare commits
No commits in common. "c68edc70d1414cda767ac300c510f0bbe20a141e" and "e71831cf9d2bbcc7011026d77500b95c62cc2a6a" have entirely different histories.
c68edc70d1
...
e71831cf9d
|
|
@ -38,6 +38,14 @@ func (a *App) handleDashboard(w http.ResponseWriter, r *http.Request) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("dashboard: stack check failed for %s: %v", remoteUser, err)
|
log.Printf("dashboard: stack check failed for %s: %v", remoteUser, err)
|
||||||
}
|
}
|
||||||
|
if !exists {
|
||||||
|
log.Printf("dashboard: deploying missing stack %s", stackName)
|
||||||
|
if err := a.swarm.DeployStack(stackName, remoteUser, a.cfg.TraefikDomain); err != nil {
|
||||||
|
log.Printf("dashboard: stack deploy failed for %s: %v", remoteUser, err)
|
||||||
|
} else {
|
||||||
|
exists = true
|
||||||
|
}
|
||||||
|
}
|
||||||
stackDeployed = exists
|
stackDeployed = exists
|
||||||
if exists {
|
if exists {
|
||||||
replicas, _ := a.swarm.GetWebReplicas(stackName)
|
replicas, _ := a.swarm.GetWebReplicas(stackName)
|
||||||
|
|
|
||||||
|
|
@ -173,35 +173,35 @@
|
||||||
{{if .StackRunning}}
|
{{if .StackRunning}}
|
||||||
<p style="color: var(--muted); font-size: 0.9rem; margin-top: 0.75rem;">Your dedicated environment is accessible at:</p>
|
<p style="color: var(--muted); font-size: 0.9rem; margin-top: 0.75rem;">Your dedicated environment is accessible at:</p>
|
||||||
<a class="stack-link" href="https://{{.User}}.{{.Domain}}">{{.User}}.{{.Domain}}</a>
|
<a class="stack-link" href="https://{{.User}}.{{.Domain}}">{{.User}}.{{.Domain}}</a>
|
||||||
{{else if and .StackDeployed (not .StackRunning)}}
|
{{else if not .StackDeployed}}
|
||||||
<p style="color: var(--muted); font-size: 0.9rem; margin-top: 0.75rem;">Your stack is stopped. Start it to access your environment.</p>
|
<p style="color: var(--muted); font-size: 0.9rem; margin-top: 0.75rem;">Your stack is being provisioned. Refresh this page in a moment.</p>
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|
||||||
|
{{if .StackDeployed}}
|
||||||
<hr class="divider">
|
<hr class="divider">
|
||||||
<div class="actions">
|
<div class="actions">
|
||||||
{{if .StackRunning}}
|
{{if .StackRunning}}
|
||||||
<form method="POST" action="/stack-manage" style="margin:0" data-stack-action>
|
<form method="POST" action="/stack-manage" style="margin:0">
|
||||||
<input type="hidden" name="action" value="restart">
|
<input type="hidden" name="action" value="restart">
|
||||||
<button type="submit" class="btn btn-outline btn-sm">Restart</button>
|
<button type="submit" class="btn btn-outline btn-sm">Restart</button>
|
||||||
</form>
|
</form>
|
||||||
<form method="POST" action="/stack-manage" style="margin:0" data-stack-action>
|
<form method="POST" action="/stack-manage" style="margin:0">
|
||||||
<input type="hidden" name="action" value="stop">
|
<input type="hidden" name="action" value="stop">
|
||||||
<button type="submit" class="btn btn-warning btn-sm">Stop</button>
|
<button type="submit" class="btn btn-warning btn-sm">Stop</button>
|
||||||
</form>
|
</form>
|
||||||
{{else}}
|
{{else}}
|
||||||
<form method="POST" action="/stack-manage" style="margin:0" data-stack-action>
|
<form method="POST" action="/stack-manage" style="margin:0">
|
||||||
<input type="hidden" name="action" value="start">
|
<input type="hidden" name="action" value="start">
|
||||||
<button type="submit" class="btn btn-sm">Start</button>
|
<button type="submit" class="btn btn-sm">Start</button>
|
||||||
</form>
|
</form>
|
||||||
{{end}}
|
{{end}}
|
||||||
{{if .StackDeployed}}
|
<form method="POST" action="/stack-manage" style="margin:0"
|
||||||
<form method="POST" action="/stack-manage" style="margin:0" data-stack-action
|
onsubmit="return confirm('Destroy your stack? All containers will be removed. Volumes are preserved.')">
|
||||||
data-confirm="Destroy your stack? All containers will be removed. Volumes are preserved.">
|
|
||||||
<input type="hidden" name="action" value="destroy">
|
<input type="hidden" name="action" value="destroy">
|
||||||
<button type="submit" class="btn btn-danger btn-sm">Destroy</button>
|
<button type="submit" class="btn btn-danger btn-sm">Destroy</button>
|
||||||
</form>
|
</form>
|
||||||
{{end}}
|
|
||||||
</div>
|
</div>
|
||||||
|
{{end}}
|
||||||
</div>
|
</div>
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<h2>Manage</h2>
|
<h2>Manage</h2>
|
||||||
|
|
@ -244,18 +244,5 @@
|
||||||
{{end}}
|
{{end}}
|
||||||
</div>
|
</div>
|
||||||
<div class="version-badge">{{.Commit}}</div>
|
<div class="version-badge">{{.Commit}}</div>
|
||||||
<script>
|
|
||||||
const pending = { restart:'Restarting…', stop:'Stopping…', start:'Starting…', destroy:'Destroying…' };
|
|
||||||
document.querySelectorAll('form[data-stack-action]').forEach(function(form) {
|
|
||||||
form.addEventListener('submit', function(e) {
|
|
||||||
var msg = form.dataset.confirm;
|
|
||||||
if (msg && !confirm(msg)) { e.preventDefault(); return; }
|
|
||||||
var btn = form.querySelector('button');
|
|
||||||
var action = (form.querySelector('input[name="action"]') || {}).value;
|
|
||||||
btn.disabled = true;
|
|
||||||
btn.textContent = pending[action] || '…';
|
|
||||||
});
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
||||||
|
|
@ -1,21 +1,17 @@
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
# CUSTOMER STACK TEMPLATE — Gitea + PostgreSQL
|
# CUSTOMER STACK TEMPLATE — Uptime Kuma
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
# This is the Docker Swarm stack deployed for each paying customer.
|
# This is the Docker Swarm stack that gets deployed for each paying customer.
|
||||||
# It defines what product/service they receive when they subscribe.
|
# It defines what product/service they receive when they subscribe.
|
||||||
#
|
#
|
||||||
# PRODUCT: Gitea — a self-hosted Git service, backed by PostgreSQL.
|
# PRODUCT: Uptime Kuma — a self-hosted uptime/monitoring dashboard.
|
||||||
# Each customer gets their own isolated instance at their subdomain.
|
# Each customer gets their own isolated instance at their subdomain.
|
||||||
#
|
#
|
||||||
# Structure:
|
# To sell a different product, replace the `web` service image and adjust
|
||||||
# web — the application, exposed via Traefik behind Authelia auth
|
# the port in the Traefik loadbalancer label accordingly.
|
||||||
# db — PostgreSQL, internal only (backend network, never exposed)
|
|
||||||
#
|
|
||||||
# To sell a different product: replace the `web` image, update the port
|
|
||||||
# in the Traefik loadbalancer label, and adjust `db` env/image as needed.
|
|
||||||
#
|
#
|
||||||
# Template variables (injected at deploy time by swarm/client.go):
|
# Template variables (injected at deploy time by swarm/client.go):
|
||||||
# {{.ID}} - customer's username (unique resource naming)
|
# {{.ID}} - customer's username (used for unique resource naming)
|
||||||
# {{.Subdomain}} - customer's subdomain (same as ID by default)
|
# {{.Subdomain}} - customer's subdomain (same as ID by default)
|
||||||
# {{.Domain}} - base domain (e.g. bc.a250.ca)
|
# {{.Domain}} - base domain (e.g. bc.a250.ca)
|
||||||
# {{.TraefikNetwork}} - Traefik overlay network name
|
# {{.TraefikNetwork}} - Traefik overlay network name
|
||||||
|
|
@ -23,23 +19,16 @@
|
||||||
# Each customer gets their stack at: https://{{.Subdomain}}.{{.Domain}}
|
# Each customer gets their stack at: https://{{.Subdomain}}.{{.Domain}}
|
||||||
# Access is restricted to the owning user via Authelia forward-auth.
|
# Access is restricted to the owning user via Authelia forward-auth.
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
|
|
||||||
|
version: "3.8"
|
||||||
|
|
||||||
services:
|
services:
|
||||||
web:
|
web:
|
||||||
image: gitea/gitea:1-rootless
|
image: louislam/uptime-kuma:1
|
||||||
environment:
|
|
||||||
GITEA__database__DB_TYPE: postgres
|
|
||||||
GITEA__database__HOST: db:5432
|
|
||||||
GITEA__database__NAME: gitea
|
|
||||||
GITEA__database__USER: gitea
|
|
||||||
GITEA__database__PASSWD: gitea
|
|
||||||
GITEA__server__DOMAIN: "{{.Subdomain}}.{{.Domain}}"
|
|
||||||
GITEA__server__ROOT_URL: "https://{{.Subdomain}}.{{.Domain}}"
|
|
||||||
GITEA__server__HTTP_PORT: "3000"
|
|
||||||
volumes:
|
volumes:
|
||||||
- gitea_data:/var/lib/gitea
|
- uptime_data:/app/data
|
||||||
networks:
|
networks:
|
||||||
- traefik_net
|
- traefik_net
|
||||||
- backend
|
|
||||||
deploy:
|
deploy:
|
||||||
replicas: 1
|
replicas: 1
|
||||||
labels:
|
labels:
|
||||||
|
|
@ -49,22 +38,7 @@ services:
|
||||||
traefik.http.routers.customer-{{.ID}}-web.entrypoints: "websecure"
|
traefik.http.routers.customer-{{.ID}}-web.entrypoints: "websecure"
|
||||||
traefik.http.routers.customer-{{.ID}}-web.tls: "true"
|
traefik.http.routers.customer-{{.ID}}-web.tls: "true"
|
||||||
traefik.http.routers.customer-{{.ID}}-web.middlewares: "authelia-auth@swarm"
|
traefik.http.routers.customer-{{.ID}}-web.middlewares: "authelia-auth@swarm"
|
||||||
traefik.http.services.customer-{{.ID}}-web.loadbalancer.server.port: "3000"
|
traefik.http.services.customer-{{.ID}}-web.loadbalancer.server.port: "3001"
|
||||||
restart_policy:
|
|
||||||
condition: on-failure
|
|
||||||
|
|
||||||
db:
|
|
||||||
image: postgres:16-alpine
|
|
||||||
environment:
|
|
||||||
POSTGRES_DB: gitea
|
|
||||||
POSTGRES_USER: gitea
|
|
||||||
POSTGRES_PASSWORD: gitea
|
|
||||||
volumes:
|
|
||||||
- db_data:/var/lib/postgresql/data
|
|
||||||
networks:
|
|
||||||
- backend
|
|
||||||
deploy:
|
|
||||||
replicas: 1
|
|
||||||
restart_policy:
|
restart_policy:
|
||||||
condition: on-failure
|
condition: on-failure
|
||||||
|
|
||||||
|
|
@ -72,11 +46,7 @@ networks:
|
||||||
traefik_net:
|
traefik_net:
|
||||||
external: true
|
external: true
|
||||||
name: "atlas_{{.TraefikNetwork}}"
|
name: "atlas_{{.TraefikNetwork}}"
|
||||||
backend:
|
|
||||||
driver: overlay
|
|
||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
gitea_data:
|
uptime_data:
|
||||||
driver: local
|
|
||||||
db_data:
|
|
||||||
driver: local
|
driver: local
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue