Merge pull request 'Copied all stacks' (#1) from dev into main

Reviewed-on: #1
This commit was merged in pull request #1.
This commit is contained in:
2026-04-11 09:53:34 +02:00
25 changed files with 1040 additions and 4 deletions

View File

@@ -1,18 +1,20 @@
# 1. Install using script # Webmin Installation commands
## 1. Install using script
```bash ```bash
curl -o webmin-setup-repo.sh https://raw.githubusercontent.com/webmin/webmin/master/webmin-setup-repo.sh curl -o webmin-setup-repo.sh https://raw.githubusercontent.com/webmin/webmin/master/webmin-setup-repo.sh
sudo sh webmin-setup-repo.sh sudo sh webmin-setup-repo.sh
``` ```
# 2. Install Webmin ## 2. Install Webmin
```shell ```shell
sudo apt update sudo apt update
sudo apt install webmin sudo apt install webmin
``` ```
# 3. Open port ## 3. Open port
```bash ```bash
ufw allow 10000 ufw allow 10000

View File

@@ -0,0 +1,12 @@
services:
dockhand:
image: fnsys/dockhand:latest
container_name: dockhand
restart: unless-stopped
ports:
- "3000:3000"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- dockhand_data:/app/data
volumes:
dockhand_data:

View File

@@ -0,0 +1,15 @@
version: '3.8'
services:
nexus:
image: sonatype/nexus3:latest
container_name: nexus-mirror
restart: always
ports:
- "4009:8081"
- "4010:8082"
environment:
# Memory limits: Adjust based on your VM capacity
- INSTALL4J_ADD_VM_PARAMS=-Xms2g -Xmx2g -XX:MaxDirectMemorySize=2g -Dnexus.secrets.file=/nexus-data/nexus.secrets.json
volumes:
- ./nexus-data:/nexus-data

View File

@@ -0,0 +1,15 @@
version: '3.8'
services:
pgadmin:
image: dpage/pgadmin4
container_name: pgadmin
environment:
PGADMIN_DEFAULT_EMAIL: khwezi@litecharms.co.za
PGADMIN_DEFAULT_PASSWORD: Blackstar2@home
ports:
- "8080:80"
volumes:
- pgadmin-data:/var/lib/pgadmin
volumes:
pgadmin-data:

View File

@@ -0,0 +1,17 @@
services:
portainer:
container_name: portainer
image: portainer/portainer-ce:lts
restart: always
extra_hosts:
- "id.khongisa.co.za:192.168.1.171"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- portainer_data:/data
ports:
- 9443:9443
- 8000:8000
volumes:
portainer_data:
name: portainer_data

View File

@@ -0,0 +1,14 @@
version: '3'
services:
registry:
image: registry:2
ports:
- "3003:5000"
environment:
REGISTRY_AUTH: token
REGISTRY_AUTH_TOKEN_REALM: https://gitea.khongisa.co.za/v2/token
REGISTRY_AUTH_TOKEN_SERVICE: gitea
REGISTRY_AUTH_TOKEN_ISSUER: gitea
volumes:
- ./data:/var/lib/registry
- ./config.yml:/etc/docker/registry/config.yml

View File

@@ -0,0 +1,86 @@
services:
server:
command: server
env_file:
- .env
environment:
AUTHENTIK_POSTGRESQL__HOST: 192.168.1.170
AUTHENTIK_POSTGRESQL__NAME: authentik
AUTHENTIK_POSTGRESQL__PASSWORD: 2h1y7H1kjdfdCLmd992SDL2iwtyjZ1iZb2X4SROK4GMvBiht
AUTHENTIK_POSTGRESQL__USER: authentik
AUTHENTIK_SECRET_KEY: ${AUTHENTIK_SECRET_KEY:?secret key required}
AUTHENTIK_LISTEN__TRUSTED_PROXY_CIDRS: 169.255.58.144/32, 192.168.1.0/24
AUTHENTIK_HOST_BROWSER: https://id.khongisa.co.za
AUTHENTIK_HOST: https://id.khongisa.co.za
AUTHENTIK_INSECURE: false
AUTHENTIK_ERROR_REPORTING__ENABLED: true
COMPOSE_PORT_HTTP: 80
COMPOSE_PORT_HTTPS: 443
AUTHENTIK_EMAIL__HOST: mail.litecharms.co.za
AUTHENTIK_EMAIL__PORT: 465
AUTHENTIK_EMAIL__USERNAME: authentik@litecharms.co.za
AUTHENTIK_EMAIL__PASSWORD: N<7`7986ZyHL
AUTHENTIK_EMAIL__USE_TLS: true
AUTHENTIK_EMAIL__USE_SSL: true
AUTHENTIK_EMAIL__TIMEOUT: 10
AUTHENTIK_EMAIL__FROM: authentik@litecharms.co.za
AUTHENTIK_POSTGRESQL__CONN_MAX_AGE: 60
AUTHENTIK_POSTGRESQL__CONN_HEALTH_CHECKS: "true"
AUTHENTIK_WORKER__THREADS: 8
AUTHENTIK_POSTGRESQL__DISABLE_SERVER_SIDE_CURSORS: "true"
AUTHENTIK_SERVER__WORKERS: 3
AUTHENTIK_SERVER__THREADS: 4
AUTHENTIK_LOG_LEVEL: warning
image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2026.2.1}
ports:
- ${COMPOSE_PORT_HTTP:-9000}:9000
- ${COMPOSE_PORT_HTTPS:-9443}:9443
restart: unless-stopped
shm_size: 512mb
volumes:
- ./data:/data
- ./custom-templates:/templates
worker:
command: worker
env_file:
- .env
environment:
AUTHENTIK_POSTGRESQL__HOST: 192.168.1.170
AUTHENTIK_POSTGRESQL__NAME: authentik
AUTHENTIK_POSTGRESQL__PASSWORD: 2h1y7H1kjdfdCLmd992SDL2iwtyjZ1iZb2X4SROK4GMvBiht
AUTHENTIK_POSTGRESQL__USER: authentik
AUTHENTIK_SECRET_KEY: ${AUTHENTIK_SECRET_KEY:?secret key required}
AUTHENTIK_LISTEN__TRUSTED_PROXY_CIDRS: 169.255.58.144/32, 192.168.1.0/24
AUTHENTIK_HOST_BROWSER: https://id.khongisa.co.za
AUTHENTIK_HOST: https://id.khongisa.co.za
AUTHENTIK_INSECURE: false
AUTHENTIK_ERROR_REPORTING__ENABLED: true
COMPOSE_PORT_HTTP: 80
COMPOSE_PORT_HTTPS: 443
AUTHENTIK_EMAIL__HOST: mail.litecharms.co.za
AUTHENTIK_EMAIL__PORT: 465
AUTHENTIK_EMAIL__USERNAME: authentik@litecharms.co.za
AUTHENTIK_EMAIL__PASSWORD: N<7`7986ZyHL
AUTHENTIK_EMAIL__USE_TLS: true
AUTHENTIK_EMAIL__USE_SSL: true
AUTHENTIK_EMAIL__TIMEOUT: 10
AUTHENTIK_EMAIL__FROM: authentik@litecharms.co.za
AUTHENTIK_POSTGRESQL__CONN_MAX_AGE: 60
AUTHENTIK_POSTGRESQL__CONN_HEALTH_CHECKS: "true"
AUTHENTIK_POSTGRESQL__DISABLE_SERVER_SIDE_CURSORS: "true"
AUTHENTIK_WORKER__PROCESSES: 2
AUTHENTIK_WORKER__THREADS: 12
AUTHENTIK_LOG_LEVEL: warning
AUTHENTIK_BLUEPRINTS__RESCAN: "false"
image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2026.2.1}
restart: unless-stopped
shm_size: 512mb
user: root
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- ./data:/data
- ./certs:/certs
- ./custom-templates:/templates
volumes:
database:
driver: local

View File

@@ -0,0 +1,10 @@
services:
hawser:
image: ghcr.io/finsys/hawser:latest
container_name: hawzer
restart: unless-stopped
environment:
- DOCKHAND_SERVER_URL=ws://192.168.1.173:3000
- TOKEN=4epVzroLNuzLw4rnB7IvwYwPcTHaS8R6DkeRPxK8t48
volumes:
- /var/run/docker.sock:/var/run/docker.sock

View File

@@ -0,0 +1,35 @@
# To see all available options, please visit the docs:
# https://docs.pangolin.net/
gerbil:
start_port: 51820
base_endpoint: "khongisa.co.za"
app:
dashboard_url: "https://khongisa.co.za"
log_level: "info"
telemetry:
anonymous_usage: true
domains:
domain1:
base_domain: "khongisa.co.za"
server:
secret: "WlCd2hoEWpQgE+XyHBn+xjQ5t/Irh91+i4krsnUgPog="
cors:
origins: ["https://khongisa.co.za"]
methods: ["GET", "POST", "PUT", "DELETE", "PATCH"]
allowed_headers: ["X-CSRF-Token", "Content-Type"]
credentials: false
maxmind_db_path: "./config/GeoLite2-Country.mmdb"
flags:
require_email_verification: false
disable_signup_without_invite: true
disable_user_create_org: false
allow_raw_resources: true
crowdsec:
enabled: true
appsec_body_limit: 0

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,91 @@
http:
middlewares:
nexus-buffer:
buffering:
maxRequestBodyBytes: 0
memRequestBodyBytes: 2097152 # 2MB
crowdsec:
plugin:
crowdsec:
crowdsecAppsecBodyLimit: 0
badger:
plugin:
badger:
disableForwardAuth: true
redirect-to-https:
redirectScheme:
scheme: https
routers:
nexus-docker-router:
rule: "Host(`nexus.khongisa.co.za`) && PathPrefix(`/v2`)"
service: api-service # Or whichever service points to Pangolin port 3000/3001
entryPoints:
- websecure
middlewares:
- nexus-buffer
- badger
tls:
certResolver: letsencrypt
# HTTP to HTTPS redirect router
main-app-router-redirect:
rule: "Host(`khongisa.co.za`)"
service: next-service
entryPoints:
- web
middlewares:
- redirect-to-https
- badger
# Next.js router (handles everything except API and WebSocket paths)
next-router:
rule: "Host(`khongisa.co.za`) && !PathPrefix(`/api/v1`)"
service: next-service
entryPoints:
- websecure
middlewares:
- badger
tls:
certResolver: letsencrypt
# API router (handles /api/v1 paths)
api-router:
rule: "Host(`khongisa.co.za`) && PathPrefix(`/api/v1`)"
service: api-service
entryPoints:
- websecure
middlewares:
- badger
tls:
certResolver: letsencrypt
# WebSocket router
ws-router:
rule: "Host(`khongisa.co.za`)"
service: api-service
entryPoints:
- websecure
middlewares:
- badger
tls:
certResolver: letsencrypt
services:
next-service:
loadBalancer:
servers:
- url: "http://pangolin:3002" # Next.js server
api-service:
loadBalancer:
servers:
- url: "http://pangolin:3000" # API/WebSocket server
tcp:
serversTransports:
pp-transport-v1:
proxyProtocol:
version: 1
pp-transport-v2:
proxyProtocol:
version: 2

View File

@@ -0,0 +1,73 @@
http:
middlewares:
badger:
plugin:
badger:
disableForwardAuth: true
redirect-to-https:
redirectScheme:
scheme: https
routers:
# HTTP to HTTPS redirect router
main-app-router-redirect:
rule: "Host(`khongisa.co.za`)"
service: next-service
entryPoints:
- web
middlewares:
- redirect-to-https
- badger
# Next.js router (handles everything except API and WebSocket paths)
next-router:
rule: "Host(`khongisa.co.za`) && !PathPrefix(`/api/v1`)"
service: next-service
entryPoints:
- websecure
middlewares:
- badger
tls:
certResolver: letsencrypt
# API router (handles /api/v1 paths)
api-router:
rule: "Host(`khongisa.co.za`) && PathPrefix(`/api/v1`)"
service: api-service
entryPoints:
- websecure
middlewares:
- badger
tls:
certResolver: letsencrypt
# WebSocket router
ws-router:
rule: "Host(`khongisa.co.za`)"
service: api-service
entryPoints:
- websecure
middlewares:
- badger
tls:
certResolver: letsencrypt
services:
next-service:
loadBalancer:
servers:
- url: "http://pangolin:3002" # Next.js server
api-service:
loadBalancer:
servers:
- url: "http://pangolin:3000" # API/WebSocket server
tcp:
serversTransports:
pp-transport-v1:
proxyProtocol:
version: 1
pp-transport-v2:
proxyProtocol:
version: 2

View File

@@ -0,0 +1,77 @@
http:
middlewares:
crowdsec:
plugin:
crowdsec:
crowdsecAppsecBodyLimit: 0
badger:
plugin:
badger:
disableForwardAuth: true
redirect-to-https:
redirectScheme:
scheme: https
routers:
# HTTP to HTTPS redirect router
main-app-router-redirect:
rule: "Host(`khongisa.co.za`)"
service: next-service
entryPoints:
- web
middlewares:
- redirect-to-https
- badger
# Next.js router (handles everything except API and WebSocket paths)
next-router:
rule: "Host(`khongisa.co.za`) && !PathPrefix(`/api/v1`)"
service: next-service
entryPoints:
- websecure
middlewares:
- badger
tls:
certResolver: letsencrypt
# API router (handles /api/v1 paths)
api-router:
rule: "Host(`khongisa.co.za`) && PathPrefix(`/api/v1`)"
service: api-service
entryPoints:
- websecure
middlewares:
- badger
tls:
certResolver: letsencrypt
# WebSocket router
ws-router:
rule: "Host(`khongisa.co.za`)"
service: api-service
entryPoints:
- websecure
middlewares:
- badger
tls:
certResolver: letsencrypt
services:
next-service:
loadBalancer:
servers:
- url: "http://pangolin:3002" # Next.js server
api-service:
loadBalancer:
servers:
- url: "http://pangolin:3000" # API/WebSocket server
tcp:
serversTransports:
pp-transport-v1:
proxyProtocol:
version: 1
pp-transport-v2:
proxyProtocol:
version: 2

View File

@@ -0,0 +1,58 @@
api:
insecure: true
dashboard: true
providers:
http:
endpoint: "http://pangolin:3001/api/v1/traefik-config"
pollInterval: "5s"
file:
filename: "/etc/traefik/dynamic_config.yml"
experimental:
plugins:
badger:
moduleName: "github.com/fosrl/badger"
version: "v1.3.1"
log:
level: "INFO"
format: "common"
maxSize: 100
maxBackups: 3
maxAge: 3
compress: true
certificatesResolvers:
letsencrypt:
acme:
httpChallenge:
entryPoint: web
email: "contact@litecharms.co.za"
storage: "/letsencrypt/acme.json"
caServer: "https://acme-v02.api.letsencrypt.org/directory"
entryPoints:
web:
address: ":80"
websecure:
address: ":443"
transport:
respondingTimeouts:
readTimeout: "0"
idleTimeout: "1200s"
#readTimeout: "30m"
http:
tls:
certResolver: "letsencrypt"
encodedCharacters:
allowEncodedSlash: true
allowEncodedQuestionMark: true
udp-51821:
address: ":51821/udp"
serversTransport:
insecureSkipVerify: true
ping:
entryPoint: "web"

View File

@@ -0,0 +1,56 @@
api:
insecure: true
dashboard: true
providers:
http:
endpoint: "http://pangolin:3001/api/v1/traefik-config"
pollInterval: "5s"
file:
filename: "/etc/traefik/dynamic_config.yml"
experimental:
plugins:
badger:
moduleName: "github.com/fosrl/badger"
version: "v1.3.1"
log:
level: "INFO"
format: "common"
maxSize: 100
maxBackups: 3
maxAge: 3
compress: true
certificatesResolvers:
letsencrypt:
acme:
httpChallenge:
entryPoint: web
email: "contact@litecharms.co.za"
storage: "/letsencrypt/acme.json"
caServer: "https://acme-v02.api.letsencrypt.org/directory"
entryPoints:
web:
address: ":80"
websecure:
address: ":443"
transport:
respondingTimeouts:
readTimeout: "30m"
http:
tls:
certResolver: "letsencrypt"
encodedCharacters:
allowEncodedSlash: true
allowEncodedQuestionMark: true
udp-51821:
address: ":51821/udp"
serversTransport:
insecureSkipVerify: true
ping:
entryPoint: "web"

View File

@@ -0,0 +1,69 @@
name: pangolin
networks:
proxy_net:
driver: bridge
services:
pangolin:
image: docker.io/fosrl/pangolin:ee-1.17.0
container_name: pangolin
restart: unless-stopped
volumes:
- ./config:/app/config
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3001/api/v1/"]
interval: "10s"
timeout: "10s"
retries: 15
networks:
- proxy_net
deploy:
resources:
reservations:
memory: 800M
limits:
memory: 3G
gerbil:
image: docker.io/fosrl/gerbil:1.3.0
container_name: gerbil
restart: unless-stopped
depends_on:
pangolin:
condition: service_healthy
command:
- --reachableAt=http://gerbil:3004
- --generateAndSaveKeyTo=/var/config/key
- --remoteConfig=http://pangolin:3001/api/v1/
volumes:
- ./config/:/var/config
cap_add:
- NET_ADMIN
- SYS_MODULE
ports:
- 51821:51821/udp
- 51820:51820/udp
- 21820:21820/udp
- 443:443
- 80:80
networks:
- proxy_net
traefik:
image: docker.io/traefik:v3.6
container_name: traefik
restart: unless-stopped
network_mode: service:gerbil
depends_on:
pangolin:
condition: service_healthy
command:
- --configFile=/etc/traefik/traefik_config.yml
volumes:
- ./config/traefik:/etc/traefik:ro
- ./config/letsencrypt:/letsencrypt
- ./config/traefik/logs:/var/log/traefik
- /var/run/docker.sock:/var/run/docker.sock:ro

View File

@@ -0,0 +1,69 @@
name: pangolin
networks:
proxy_net:
driver: bridge
services:
pangolin:
image: docker.io/fosrl/pangolin:ee-1.16.2
container_name: pangolin
restart: unless-stopped
volumes:
- ./config:/app/config
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3001/api/v1/"]
interval: "10s"
timeout: "10s"
retries: 15
networks:
- proxy_net
deploy:
resources:
reservations:
memory: 800M
limits:
memory: 3G
gerbil:
image: docker.io/fosrl/gerbil:1.3.0
container_name: gerbil
restart: unless-stopped
depends_on:
pangolin:
condition: service_healthy
command:
- --reachableAt=http://gerbil:3004
- --generateAndSaveKeyTo=/var/config/key
- --remoteConfig=http://pangolin:3001/api/v1/
volumes:
- ./config/:/var/config
cap_add:
- NET_ADMIN
- SYS_MODULE
ports:
- 51821:51821/udp
- 51820:51820/udp
- 21820:21820/udp
- 443:443
- 80:80
networks:
- proxy_net
traefik:
image: docker.io/traefik:v3.6
container_name: traefik
restart: unless-stopped
network_mode: service:gerbil
depends_on:
pangolin:
condition: service_healthy
command:
- --configFile=/etc/traefik/traefik_config.yml
volumes:
- ./config/traefik:/etc/traefik:ro
- ./config/letsencrypt:/letsencrypt
- ./config/traefik/logs:/var/log/traefik
- /var/run/docker.sock:/var/run/docker.sock:ro