Compare commits
46 Commits
608cc9253d
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| 272250d4c2 | |||
| 9ad35b77d8 | |||
| 077d40321d | |||
| adfeb664c9 | |||
| 1463bbced1 | |||
| eed6196da5 | |||
| 0970e97a8f | |||
| 53332d416a | |||
| ca456e8ee6 | |||
| c616d63083 | |||
| deb2403bad | |||
| 0cbe7d3862 | |||
| 2a1d78fa69 | |||
| 6b5fcb2f61 | |||
| d6a3d9a3f6 | |||
| c5e416d31c | |||
| a4dfbc715f | |||
| b14015b12f | |||
| 6e22713454 | |||
| a0b6dcbdc3 | |||
| e944ac8b48 | |||
| 2609411fd8 | |||
| 477e22d5a6 | |||
| 32e7536fd8 | |||
| 7704551668 | |||
| f949992127 | |||
| b2971e1f89 | |||
| c91a89a33e | |||
| e5b14eee4e | |||
| 6559870e06 | |||
| db0745e57d | |||
| cb9a8fa46b | |||
| 382292c52f | |||
| aa2646c907 | |||
| f46817fa7a | |||
| 244794d15f | |||
| e2372fd67a | |||
| 68660717f2 | |||
| b19a0aa195 | |||
| 5388ef16d7 | |||
| 195c6860b5 | |||
| ba27db032e | |||
| 5807713e22 | |||
| 55e1e0a400 | |||
| 9f61b06592 | |||
| d7b65f9f6d |
@@ -27,15 +27,32 @@ jobs:
|
|||||||
STACKS=$(git diff --name-only HEAD~1 HEAD 2>/dev/null | grep '^stacks/' | cut -d'/' -f2 | sort -u || echo "")
|
STACKS=$(git diff --name-only HEAD~1 HEAD 2>/dev/null | grep '^stacks/' | cut -d'/' -f2 | sort -u || echo "")
|
||||||
|
|
||||||
if [ -z "$STACKS" ]; then
|
if [ -z "$STACKS" ]; then
|
||||||
echo "No stacks changed, deploying all..."
|
echo "No stacks changed, checking all stacks..."
|
||||||
STACKS=$(ls stacks/)
|
STACKS=$(ls stacks/)
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "Deploying: $STACKS"
|
echo "Evaluating stacks: $STACKS"
|
||||||
|
echo ""
|
||||||
|
|
||||||
for stack in $STACKS; do
|
for stack in $STACKS; do
|
||||||
|
COMPOSE_FILE="stacks/$stack/docker-compose.yml"
|
||||||
|
|
||||||
|
# Check stack-type label
|
||||||
|
STACK_TYPE=$(grep -o 'stack-type=[^"]*' "$COMPOSE_FILE" 2>/dev/null | head -1 | cut -d= -f2)
|
||||||
|
|
||||||
|
if [ -z "$STACK_TYPE" ]; then
|
||||||
|
echo "⚠️ SKIP $stack - no stack-type label found"
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
# On prod, only deploy 'prod' and 'public' stacks
|
||||||
|
if [ "$STACK_TYPE" != "prod" ] && [ "$STACK_TYPE" != "public" ]; then
|
||||||
|
echo "⏭️ SKIP $stack - stack-type=$STACK_TYPE (not for prod)"
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
echo "=========================================="
|
echo "=========================================="
|
||||||
echo "Deploying $stack..."
|
echo "Deploying $stack (stack-type=$STACK_TYPE)..."
|
||||||
echo "=========================================="
|
echo "=========================================="
|
||||||
|
|
||||||
STACK_DIR="${{ env.STACKS_DIR }}/$stack"
|
STACK_DIR="${{ env.STACKS_DIR }}/$stack"
|
||||||
@@ -44,9 +61,10 @@ jobs:
|
|||||||
# Copy files
|
# Copy files
|
||||||
sudo cp -r stacks/$stack/* "$STACK_DIR/"
|
sudo cp -r stacks/$stack/* "$STACK_DIR/"
|
||||||
|
|
||||||
# Create .env from template if exists
|
# Create .env from template if .env doesn't exist
|
||||||
if [ -f "$STACK_DIR/.env.template" ]; then
|
if [ -f "$STACK_DIR/.env.template" ] && [ ! -f "$STACK_DIR/.env" ]; then
|
||||||
sudo envsubst < "$STACK_DIR/.env.template" > "$STACK_DIR/.env"
|
echo "Creating .env from template..."
|
||||||
|
sudo sh -c "DOMAIN=$DOMAIN envsubst < '$STACK_DIR/.env.template' > '$STACK_DIR/.env'"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Deploy
|
# Deploy
|
||||||
@@ -59,11 +77,11 @@ jobs:
|
|||||||
done
|
done
|
||||||
|
|
||||||
- name: Show running containers
|
- name: Show running containers
|
||||||
run: sudo docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}" | head -20
|
run: sudo docker ps --format "table {{.Names}}\t{{.Status}}" | head -30 || true
|
||||||
|
|
||||||
deploy-dev:
|
deploy-dev:
|
||||||
if: ${{ github.ref == 'refs/heads/dev' }}
|
if: ${{ github.ref == 'refs/heads/dev' }}
|
||||||
runs-on: ubuntu-dev
|
runs-on: ubuntu-dev:host
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
@@ -77,15 +95,32 @@ jobs:
|
|||||||
STACKS=$(git diff --name-only HEAD~1 HEAD 2>/dev/null | grep '^stacks/' | cut -d'/' -f2 | sort -u || echo "")
|
STACKS=$(git diff --name-only HEAD~1 HEAD 2>/dev/null | grep '^stacks/' | cut -d'/' -f2 | sort -u || echo "")
|
||||||
|
|
||||||
if [ -z "$STACKS" ]; then
|
if [ -z "$STACKS" ]; then
|
||||||
echo "No stacks changed, deploying all..."
|
echo "No stacks changed, checking all stacks..."
|
||||||
STACKS=$(ls stacks/)
|
STACKS=$(ls stacks/)
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "Deploying: $STACKS"
|
echo "Evaluating stacks: $STACKS"
|
||||||
|
echo ""
|
||||||
|
|
||||||
for stack in $STACKS; do
|
for stack in $STACKS; do
|
||||||
|
COMPOSE_FILE="stacks/$stack/docker-compose.yml"
|
||||||
|
|
||||||
|
# Check stack-type label
|
||||||
|
STACK_TYPE=$(grep -o 'stack-type=[^"]*' "$COMPOSE_FILE" 2>/dev/null | head -1 | cut -d= -f2)
|
||||||
|
|
||||||
|
if [ -z "$STACK_TYPE" ]; then
|
||||||
|
echo "⚠️ SKIP $stack - no stack-type label found"
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
# On dev, only deploy 'dev-only' stacks
|
||||||
|
if [ "$STACK_TYPE" != "dev-only" ]; then
|
||||||
|
echo "⏭️ SKIP $stack - stack-type=$STACK_TYPE (not for dev)"
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
echo "=========================================="
|
echo "=========================================="
|
||||||
echo "Deploying $stack..."
|
echo "Deploying $stack (stack-type=$STACK_TYPE)..."
|
||||||
echo "=========================================="
|
echo "=========================================="
|
||||||
|
|
||||||
STACK_DIR="${{ env.STACKS_DIR }}/$stack"
|
STACK_DIR="${{ env.STACKS_DIR }}/$stack"
|
||||||
@@ -94,9 +129,10 @@ jobs:
|
|||||||
# Copy files
|
# Copy files
|
||||||
sudo cp -r stacks/$stack/* "$STACK_DIR/"
|
sudo cp -r stacks/$stack/* "$STACK_DIR/"
|
||||||
|
|
||||||
# Create .env from template if exists
|
# Create .env from template if .env doesn't exist
|
||||||
if [ -f "$STACK_DIR/.env.template" ]; then
|
if [ -f "$STACK_DIR/.env.template" ] && [ ! -f "$STACK_DIR/.env" ]; then
|
||||||
sudo envsubst < "$STACK_DIR/.env.template" > "$STACK_DIR/.env"
|
echo "Creating .env from template..."
|
||||||
|
sudo sh -c "DOMAIN=$DOMAIN envsubst < '$STACK_DIR/.env.template' > '$STACK_DIR/.env'"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Deploy
|
# Deploy
|
||||||
@@ -109,4 +145,4 @@ jobs:
|
|||||||
done
|
done
|
||||||
|
|
||||||
- name: Show running containers
|
- name: Show running containers
|
||||||
run: sudo docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}" | head -20
|
run: sudo docker ps --format "table {{.Names}}\t{{.Status}}" | head -30 || true
|
||||||
|
|||||||
10
README.md
10
README.md
@@ -18,6 +18,7 @@ stacks/
|
|||||||
├── perilous/ # Blog/website
|
├── perilous/ # Blog/website
|
||||||
├── ramz/ # Go web app
|
├── ramz/ # Go web app
|
||||||
├── bookclub/ # Form mailer
|
├── bookclub/ # Form mailer
|
||||||
|
├── invidious/ # YouTube frontend
|
||||||
├── watchtower/ # Auto container updates
|
├── watchtower/ # Auto container updates
|
||||||
├── dockge/ # Container management UI
|
├── dockge/ # Container management UI
|
||||||
└── smokeping/ # Network monitoring
|
└── smokeping/ # Network monitoring
|
||||||
@@ -96,6 +97,13 @@ Set these in Gitea → Repository → Settings → Actions → Secrets:
|
|||||||
|--------|-------------|
|
|--------|-------------|
|
||||||
| `PERILOUS_CODE_SERVER_PASSWORD` | Code-server password |
|
| `PERILOUS_CODE_SERVER_PASSWORD` | Code-server password |
|
||||||
|
|
||||||
|
### Invidious
|
||||||
|
| Secret | Description |
|
||||||
|
|--------|-------------|
|
||||||
|
| `INVIDIOUS_DB_PASSWORD` | PostgreSQL password |
|
||||||
|
| `INVIDIOUS_HMAC_KEY` | Generate: `openssl rand -hex 16` |
|
||||||
|
| `INVIDIOUS_COMPANION_KEY` | **Must be exactly 16 chars**: `openssl rand -base64 12` |
|
||||||
|
|
||||||
## Runner Setup
|
## Runner Setup
|
||||||
|
|
||||||
The workflow requires a self-hosted runner on the prod server:
|
The workflow requires a self-hosted runner on the prod server:
|
||||||
@@ -139,3 +147,5 @@ act_runner daemon
|
|||||||
```
|
```
|
||||||
|
|
||||||
4. Then deploy other stacks as needed.
|
4. Then deploy other stacks as needed.
|
||||||
|
# Runner test Wed 21 Jan 2026 12:08:53 AM EST
|
||||||
|
# Runner test 2 Wed 21 Jan 2026 12:11:37 AM EST
|
||||||
|
|||||||
96
scripts/test-services.sh
Executable file
96
scripts/test-services.sh
Executable file
@@ -0,0 +1,96 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# Test all service URLs to verify they're responding
|
||||||
|
# Note: Some services may not be deployed yet - failures indicate either
|
||||||
|
# the service isn't running or routing isn't configured
|
||||||
|
|
||||||
|
DOMAIN="ghost.tel"
|
||||||
|
|
||||||
|
# Colors
|
||||||
|
RED='\033[0;31m'
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
YELLOW='\033[0;33m'
|
||||||
|
NC='\033[0m' # No Color
|
||||||
|
|
||||||
|
# All service URLs
|
||||||
|
URLS=(
|
||||||
|
# ghost.tel services
|
||||||
|
"https://authentik.$DOMAIN"
|
||||||
|
"https://bookclub.$DOMAIN"
|
||||||
|
"https://brain.$DOMAIN"
|
||||||
|
"https://change.$DOMAIN"
|
||||||
|
"https://dockge.$DOMAIN"
|
||||||
|
"https://files.$DOMAIN"
|
||||||
|
"https://ghost.$DOMAIN"
|
||||||
|
"https://gitea.$DOMAIN"
|
||||||
|
"https://gollum.$DOMAIN"
|
||||||
|
"https://inv.$DOMAIN"
|
||||||
|
"https://memento.$DOMAIN"
|
||||||
|
"https://radicale.$DOMAIN"
|
||||||
|
"https://registry.$DOMAIN/v2/"
|
||||||
|
"https://smoke.$DOMAIN"
|
||||||
|
"https://syncthing.$DOMAIN"
|
||||||
|
"https://wallabag.$DOMAIN"
|
||||||
|
"https://xb.$DOMAIN"
|
||||||
|
"https://zerotierui.$DOMAIN"
|
||||||
|
|
||||||
|
# perilous.dev
|
||||||
|
"https://perilous.dev"
|
||||||
|
"https://www.perilous.dev"
|
||||||
|
"https://cs.perilous.dev"
|
||||||
|
"https://forest.perilous.dev"
|
||||||
|
"https://chapel.perilous.dev"
|
||||||
|
|
||||||
|
# uplink.tel (proxied via docker-public)
|
||||||
|
"https://nitter.uplink.tel"
|
||||||
|
"https://invidious.uplink.tel"
|
||||||
|
"https://searx.uplink.tel"
|
||||||
|
"https://freshrss.uplink.tel"
|
||||||
|
"https://rsshub.uplink.tel"
|
||||||
|
"https://radio.uplink.tel"
|
||||||
|
|
||||||
|
# sequela.tel (proxied via docker-public)
|
||||||
|
"https://wiki.sequela.tel"
|
||||||
|
"https://matomo.sequela.tel"
|
||||||
|
|
||||||
|
# Other domains
|
||||||
|
"https://spider.ghost.tel"
|
||||||
|
"https://tlc.ghost.tel"
|
||||||
|
"https://thislittlecorner.net"
|
||||||
|
"https://parker.ramz.cc"
|
||||||
|
)
|
||||||
|
|
||||||
|
echo "Testing ${#URLS[@]} service URLs..."
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
PASS=0
|
||||||
|
FAIL=0
|
||||||
|
|
||||||
|
for url in "${URLS[@]}"; do
|
||||||
|
# Get HTTP status code with 5 second timeout
|
||||||
|
status=$(curl -s -o /dev/null -w "%{http_code}" --max-time 5 "$url" 2>/dev/null)
|
||||||
|
|
||||||
|
if [[ -z "$status" || "$status" == "000" ]]; then
|
||||||
|
echo -e "${RED}FAIL${NC} $url - Connection failed/timeout"
|
||||||
|
((FAIL++))
|
||||||
|
elif [[ "$status" =~ ^[23] ]]; then
|
||||||
|
echo -e "${GREEN}PASS${NC} $url - HTTP $status"
|
||||||
|
((PASS++))
|
||||||
|
elif [[ "$status" =~ ^4 ]]; then
|
||||||
|
# 401/403 might be expected for auth-protected services
|
||||||
|
if [[ "$status" == "401" || "$status" == "403" ]]; then
|
||||||
|
echo -e "${YELLOW}AUTH${NC} $url - HTTP $status (auth required)"
|
||||||
|
((PASS++))
|
||||||
|
else
|
||||||
|
echo -e "${RED}FAIL${NC} $url - HTTP $status"
|
||||||
|
((FAIL++))
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo -e "${RED}FAIL${NC} $url - HTTP $status"
|
||||||
|
((FAIL++))
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "----------------------------------------"
|
||||||
|
echo -e "Results: ${GREEN}$PASS passed${NC}, ${RED}$FAIL failed${NC}"
|
||||||
|
exit $FAIL
|
||||||
26
stacks/analoggallery-public/docker-compose.yml
Normal file
26
stacks/analoggallery-public/docker-compose.yml
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
services:
|
||||||
|
gallery:
|
||||||
|
build:
|
||||||
|
context: https://gitea.ghost.tel/knight/analogGallery.git#main
|
||||||
|
container_name: analoggallery
|
||||||
|
restart: unless-stopped
|
||||||
|
labels:
|
||||||
|
- "com.ghost.tel/stack-type=public"
|
||||||
|
- "traefik.enable=true"
|
||||||
|
- "traefik.http.routers.analoggallery.entrypoints=https"
|
||||||
|
- "traefik.http.routers.analoggallery.rule=Host(`analog.uplink.tel`)"
|
||||||
|
- "traefik.http.routers.analoggallery.tls.certresolver=http"
|
||||||
|
- "traefik.http.services.analoggallery.loadbalancer.server.port=3000"
|
||||||
|
environment:
|
||||||
|
- NODE_ENV=production
|
||||||
|
volumes:
|
||||||
|
- ./images:/app/images
|
||||||
|
- ./images.json:/app/images.json
|
||||||
|
expose:
|
||||||
|
- "3000"
|
||||||
|
networks:
|
||||||
|
- web
|
||||||
|
|
||||||
|
networks:
|
||||||
|
web:
|
||||||
|
external: true
|
||||||
1
stacks/astro/.env.template
Normal file
1
stacks/astro/.env.template
Normal file
@@ -0,0 +1 @@
|
|||||||
|
DOMAIN=${DOMAIN}
|
||||||
23
stacks/astro/docker-compose.yml
Normal file
23
stacks/astro/docker-compose.yml
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
services:
|
||||||
|
astro:
|
||||||
|
image: nginx:alpine
|
||||||
|
container_name: astro
|
||||||
|
restart: unless-stopped
|
||||||
|
expose:
|
||||||
|
- 80
|
||||||
|
volumes:
|
||||||
|
- ./dist:/usr/share/nginx/html:ro
|
||||||
|
- ./nginx-cors.conf:/etc/nginx/conf.d/default.conf:ro
|
||||||
|
networks:
|
||||||
|
- web
|
||||||
|
labels:
|
||||||
|
- "com.ghost.tel/stack-type=public"
|
||||||
|
- "traefik.enable=true"
|
||||||
|
- "traefik.http.routers.astro.entrypoints=https"
|
||||||
|
- "traefik.http.routers.astro.rule=Host(`e.field.${DOMAIN}`)"
|
||||||
|
- "traefik.http.routers.astro.tls.certresolver=http"
|
||||||
|
- "traefik.http.services.astro.loadbalancer.server.port=80"
|
||||||
|
|
||||||
|
networks:
|
||||||
|
web:
|
||||||
|
external: true
|
||||||
27
stacks/astro/nginx-cors.conf
Normal file
27
stacks/astro/nginx-cors.conf
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
|
||||||
|
location / {
|
||||||
|
root /usr/share/nginx/html;
|
||||||
|
index index.html index.htm;
|
||||||
|
|
||||||
|
# CORS configuration
|
||||||
|
add_header 'Access-Control-Allow-Origin' '*' always;
|
||||||
|
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS' always;
|
||||||
|
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range' always;
|
||||||
|
add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range' always;
|
||||||
|
|
||||||
|
# Handle preflight requests
|
||||||
|
if ($request_method = 'OPTIONS') {
|
||||||
|
add_header 'Access-Control-Allow-Origin' '*';
|
||||||
|
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
|
||||||
|
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
|
||||||
|
add_header 'Access-Control-Max-Age' 1728000;
|
||||||
|
add_header 'Content-Type' 'text/plain; charset=utf-8';
|
||||||
|
add_header 'Content-Length' 0;
|
||||||
|
return 204;
|
||||||
|
}
|
||||||
|
|
||||||
|
try_files $uri $uri/ =404;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,6 +3,8 @@ services:
|
|||||||
image: ghcr.io/goauthentik/server:latest
|
image: ghcr.io/goauthentik/server:latest
|
||||||
container_name: authentik-server
|
container_name: authentik-server
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
|
ports:
|
||||||
|
- "9000:9000"
|
||||||
command: server
|
command: server
|
||||||
environment:
|
environment:
|
||||||
AUTHENTIK_SECRET_KEY: ${AUTHENTIK_SECRET_KEY}
|
AUTHENTIK_SECRET_KEY: ${AUTHENTIK_SECRET_KEY}
|
||||||
@@ -23,11 +25,16 @@ services:
|
|||||||
- web
|
- web
|
||||||
- default
|
- default
|
||||||
labels:
|
labels:
|
||||||
|
- "com.ghost.tel/stack-type=prod"
|
||||||
- "traefik.enable=true"
|
- "traefik.enable=true"
|
||||||
- "traefik.http.routers.authentik.entrypoints=https"
|
- "traefik.http.routers.authentik.entrypoints=https"
|
||||||
- "traefik.http.routers.authentik.rule=Host(`authentik.${DOMAIN}`)"
|
- "traefik.http.routers.authentik.rule=Host(`authentik.${DOMAIN}`)"
|
||||||
- "traefik.http.routers.authentik.tls.certresolver=http"
|
- "traefik.http.routers.authentik.tls.certresolver=http"
|
||||||
- "traefik.http.services.authentik.loadbalancer.server.port=9000"
|
- "traefik.http.services.authentik.loadbalancer.server.port=9000"
|
||||||
|
- "traefik.http.routers.authentik-outpost.entrypoints=https"
|
||||||
|
- "traefik.http.routers.authentik-outpost.rule=HostRegexp(`{subdomain:[a-z0-9]+}.ghost.tel`) && PathPrefix(`/outpost.goauthentik.io/`)"
|
||||||
|
- "traefik.http.routers.authentik-outpost.service=authentik"
|
||||||
|
- "traefik.http.routers.authentik-outpost.tls.certresolver=http"
|
||||||
|
|
||||||
worker:
|
worker:
|
||||||
image: ghcr.io/goauthentik/server:latest
|
image: ghcr.io/goauthentik/server:latest
|
||||||
@@ -52,7 +59,7 @@ services:
|
|||||||
- redis
|
- redis
|
||||||
|
|
||||||
postgresql:
|
postgresql:
|
||||||
image: postgres:15-alpine
|
image: postgres:12-alpine
|
||||||
container_name: authentik-postgres
|
container_name: authentik-postgres
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
environment:
|
environment:
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ services:
|
|||||||
env_file:
|
env_file:
|
||||||
- .env
|
- .env
|
||||||
labels:
|
labels:
|
||||||
|
- "com.ghost.tel/stack-type=dev-only"
|
||||||
- "traefik.enable=true"
|
- "traefik.enable=true"
|
||||||
- "traefik.http.routers.form-mailer.rule=Host(`bookclub.${DOMAIN}`)"
|
- "traefik.http.routers.form-mailer.rule=Host(`bookclub.${DOMAIN}`)"
|
||||||
- "traefik.http.routers.form-mailer.entrypoints=https"
|
- "traefik.http.routers.form-mailer.entrypoints=https"
|
||||||
|
|||||||
@@ -11,11 +11,12 @@ services:
|
|||||||
networks:
|
networks:
|
||||||
- web
|
- web
|
||||||
labels:
|
labels:
|
||||||
|
- "com.ghost.tel/stack-type=prod"
|
||||||
- "traefik.enable=true"
|
- "traefik.enable=true"
|
||||||
- "traefik.http.routers.brain.entrypoints=https"
|
- "traefik.http.routers.brain.entrypoints=https"
|
||||||
- "traefik.http.routers.brain.rule=Host(`brain.${DOMAIN}`)"
|
- "traefik.http.routers.brain.rule=Host(`brain.${DOMAIN}`)"
|
||||||
- "traefik.http.routers.brain.tls.certresolver=http"
|
- "traefik.http.routers.brain.tls.certresolver=http"
|
||||||
- "traefik.http.routers.brain.middlewares=auth@file"
|
- "traefik.http.routers.brain.middlewares=auth@docker"
|
||||||
|
|
||||||
sftp:
|
sftp:
|
||||||
image: atmoz/sftp
|
image: atmoz/sftp
|
||||||
|
|||||||
@@ -13,11 +13,12 @@ services:
|
|||||||
networks:
|
networks:
|
||||||
- web
|
- web
|
||||||
labels:
|
labels:
|
||||||
|
- "com.ghost.tel/stack-type=prod"
|
||||||
- "traefik.enable=true"
|
- "traefik.enable=true"
|
||||||
- "traefik.http.routers.changedetection.entrypoints=https"
|
- "traefik.http.routers.changedetection.entrypoints=https"
|
||||||
- "traefik.http.routers.changedetection.rule=Host(`change.${DOMAIN}`)"
|
- "traefik.http.routers.changedetection.rule=Host(`change.${DOMAIN}`)"
|
||||||
- "traefik.http.routers.changedetection.tls.certresolver=http"
|
- "traefik.http.routers.changedetection.tls.certresolver=http"
|
||||||
- "traefik.http.routers.changedetection.middlewares=auth@file"
|
- "traefik.http.routers.changedetection.middlewares=auth@docker"
|
||||||
depends_on:
|
depends_on:
|
||||||
- playwright-chrome
|
- playwright-chrome
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ services:
|
|||||||
container_name: dockge
|
container_name: dockge
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
ports:
|
ports:
|
||||||
- 5001:5001
|
- 5002:5001
|
||||||
volumes:
|
volumes:
|
||||||
- /var/run/docker.sock:/var/run/docker.sock
|
- /var/run/docker.sock:/var/run/docker.sock
|
||||||
- ./data:/app/data
|
- ./data:/app/data
|
||||||
@@ -14,6 +14,7 @@ services:
|
|||||||
networks:
|
networks:
|
||||||
- web
|
- web
|
||||||
labels:
|
labels:
|
||||||
|
- "com.ghost.tel/stack-type=dev-only"
|
||||||
- "traefik.enable=true"
|
- "traefik.enable=true"
|
||||||
- "traefik.http.routers.dockge.rule=Host(`dockge.${DOMAIN}`)"
|
- "traefik.http.routers.dockge.rule=Host(`dockge.${DOMAIN}`)"
|
||||||
- "traefik.http.routers.dockge.entrypoints=https"
|
- "traefik.http.routers.dockge.entrypoints=https"
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ services:
|
|||||||
networks:
|
networks:
|
||||||
- web
|
- web
|
||||||
labels:
|
labels:
|
||||||
|
- "com.ghost.tel/stack-type=dev-only"
|
||||||
- "traefik.enable=true"
|
- "traefik.enable=true"
|
||||||
- "traefik.http.routers.filebrowser.entrypoints=https"
|
- "traefik.http.routers.filebrowser.entrypoints=https"
|
||||||
- "traefik.http.routers.filebrowser.rule=Host(`files.${DOMAIN}`)"
|
- "traefik.http.routers.filebrowser.rule=Host(`files.${DOMAIN}`)"
|
||||||
|
|||||||
23
stacks/freshrss-public/docker-compose.yml
Normal file
23
stacks/freshrss-public/docker-compose.yml
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
services:
|
||||||
|
freshrss:
|
||||||
|
image: lscr.io/linuxserver/freshrss:latest
|
||||||
|
container_name: freshrss
|
||||||
|
restart: unless-stopped
|
||||||
|
labels:
|
||||||
|
- "com.ghost.tel/stack-type=public"
|
||||||
|
- "traefik.enable=true"
|
||||||
|
- "traefik.http.routers.freshrss.entrypoints=https"
|
||||||
|
- "traefik.http.routers.freshrss.rule=Host(`freshrss.uplink.tel`)"
|
||||||
|
- "traefik.http.routers.freshrss.tls.certresolver=http"
|
||||||
|
environment:
|
||||||
|
- PUID=1000
|
||||||
|
- PGID=1000
|
||||||
|
- TZ=America/New_York
|
||||||
|
volumes:
|
||||||
|
- ./config:/config
|
||||||
|
networks:
|
||||||
|
- web
|
||||||
|
|
||||||
|
networks:
|
||||||
|
web:
|
||||||
|
external: true
|
||||||
@@ -18,6 +18,7 @@ services:
|
|||||||
volumes:
|
volumes:
|
||||||
- ./content:/var/lib/ghost/content
|
- ./content:/var/lib/ghost/content
|
||||||
labels:
|
labels:
|
||||||
|
- "com.ghost.tel/stack-type=prod"
|
||||||
- "traefik.enable=true"
|
- "traefik.enable=true"
|
||||||
- "traefik.http.routers.ghost.entrypoints=https"
|
- "traefik.http.routers.ghost.entrypoints=https"
|
||||||
- "traefik.http.routers.ghost.rule=Host(`ghost.${DOMAIN}`)"
|
- "traefik.http.routers.ghost.rule=Host(`ghost.${DOMAIN}`)"
|
||||||
|
|||||||
0
stacks/gitea/.gitkeep
Normal file
0
stacks/gitea/.gitkeep
Normal file
1
stacks/gitea/.trigger
Normal file
1
stacks/gitea/.trigger
Normal file
@@ -0,0 +1 @@
|
|||||||
|
# Trigger deploy 1768957434
|
||||||
@@ -10,6 +10,7 @@ services:
|
|||||||
- "22"
|
- "22"
|
||||||
ports:
|
ports:
|
||||||
- "2245:22"
|
- "2245:22"
|
||||||
|
- "3001:3000"
|
||||||
depends_on:
|
depends_on:
|
||||||
- db
|
- db
|
||||||
environment:
|
environment:
|
||||||
@@ -21,6 +22,7 @@ services:
|
|||||||
- default
|
- default
|
||||||
- web
|
- web
|
||||||
labels:
|
labels:
|
||||||
|
- "com.ghost.tel/stack-type=prod"
|
||||||
- "traefik.enable=true"
|
- "traefik.enable=true"
|
||||||
- "traefik.http.routers.gitea.entrypoints=https"
|
- "traefik.http.routers.gitea.entrypoints=https"
|
||||||
- "traefik.http.routers.gitea.rule=Host(`gitea.${DOMAIN}`)"
|
- "traefik.http.routers.gitea.rule=Host(`gitea.${DOMAIN}`)"
|
||||||
@@ -52,6 +54,7 @@ services:
|
|||||||
environment:
|
environment:
|
||||||
- GITEA_INSTANCE_URL=https://gitea.${DOMAIN}
|
- GITEA_INSTANCE_URL=https://gitea.${DOMAIN}
|
||||||
- GITEA_RUNNER_REGISTRATION_TOKEN=${GITEA_RUNNER_TOKEN}
|
- GITEA_RUNNER_REGISTRATION_TOKEN=${GITEA_RUNNER_TOKEN}
|
||||||
|
- GITEA_RUNNER_LABELS=ubuntu-prod:host
|
||||||
|
|
||||||
networks:
|
networks:
|
||||||
web:
|
web:
|
||||||
|
|||||||
@@ -13,11 +13,12 @@ services:
|
|||||||
networks:
|
networks:
|
||||||
- web
|
- web
|
||||||
labels:
|
labels:
|
||||||
|
- "com.ghost.tel/stack-type=prod"
|
||||||
- "traefik.enable=true"
|
- "traefik.enable=true"
|
||||||
- "traefik.http.routers.gollum.entrypoints=https"
|
- "traefik.http.routers.gollum.entrypoints=https"
|
||||||
- "traefik.http.routers.gollum.rule=Host(`gollum.${DOMAIN}`)"
|
- "traefik.http.routers.gollum.rule=Host(`gollum.${DOMAIN}`)"
|
||||||
- "traefik.http.routers.gollum.tls.certresolver=http"
|
- "traefik.http.routers.gollum.tls.certresolver=http"
|
||||||
- "traefik.http.routers.gollum.middlewares=auth@file"
|
- "traefik.http.routers.gollum.middlewares=auth@docker"
|
||||||
|
|
||||||
networks:
|
networks:
|
||||||
web:
|
web:
|
||||||
|
|||||||
28
stacks/homepage/docker-compose.yml
Normal file
28
stacks/homepage/docker-compose.yml
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
services:
|
||||||
|
homepage:
|
||||||
|
image: nginx
|
||||||
|
container_name: homepage
|
||||||
|
restart: unless-stopped
|
||||||
|
volumes:
|
||||||
|
- ./html:/usr/share/nginx/html # Mount your content directory
|
||||||
|
- ./templates:/etc/nginx/templates # Mount your templates directory
|
||||||
|
expose:
|
||||||
|
- "80"
|
||||||
|
labels:
|
||||||
|
- "traefik.enable=true"
|
||||||
|
- "traefik.http.routers.homepage-secure.entrypoints=https,http"
|
||||||
|
- "traefik.http.routers.homepage-secure.rule=Host(`ghost.tel`)"
|
||||||
|
- "traefik.http.routers.homepage-secure.tls.certresolver=http"
|
||||||
|
- "traefik.http.middlewares.watch-redirect.redirectregex.regex=https?://ghost.tel/watch(.*)"
|
||||||
|
- "traefik.http.middlewares.watch-redirect.redirectregex.replacement=https://invid.ghost.tel/watch$${1}"
|
||||||
|
- "traefik.http.middlewares.watch-redirect.redirectregex.permanent=true"
|
||||||
|
- "traefik.http.routers.homepage-secure.middlewares=watch-redirect"
|
||||||
|
# - "traefik.http.routers.homepage-secure.middlewares=auth@file"
|
||||||
|
environment:
|
||||||
|
- NGINX_HOST=ghost.tel
|
||||||
|
- NGINX_PORT=80
|
||||||
|
networks:
|
||||||
|
- web
|
||||||
|
networks:
|
||||||
|
web:
|
||||||
|
external: true
|
||||||
@@ -1,5 +1,4 @@
|
|||||||
DOMAIN=${DOMAIN}
|
DOMAIN=${DOMAIN}
|
||||||
INVIDIOUS_DB_PASSWORD=${INVIDIOUS_DB_PASSWORD}
|
INVIDIOUS_DB_PASSWORD=${INVIDIOUS_DB_PASSWORD}
|
||||||
INVIDIOUS_VISITOR_DATA=${INVIDIOUS_VISITOR_DATA}
|
|
||||||
INVIDIOUS_PO_TOKEN=${INVIDIOUS_PO_TOKEN}
|
|
||||||
INVIDIOUS_HMAC_KEY=${INVIDIOUS_HMAC_KEY}
|
INVIDIOUS_HMAC_KEY=${INVIDIOUS_HMAC_KEY}
|
||||||
|
INVIDIOUS_COMPANION_KEY=${INVIDIOUS_COMPANION_KEY}
|
||||||
|
|||||||
12
stacks/invidious/config/sql/annotations.sql
Normal file
12
stacks/invidious/config/sql/annotations.sql
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
-- Table: public.annotations
|
||||||
|
|
||||||
|
-- DROP TABLE public.annotations;
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS public.annotations
|
||||||
|
(
|
||||||
|
id text NOT NULL,
|
||||||
|
annotations xml,
|
||||||
|
CONSTRAINT annotations_id_key UNIQUE (id)
|
||||||
|
);
|
||||||
|
|
||||||
|
GRANT ALL ON TABLE public.annotations TO current_user;
|
||||||
30
stacks/invidious/config/sql/channel_videos.sql
Normal file
30
stacks/invidious/config/sql/channel_videos.sql
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
-- Table: public.channel_videos
|
||||||
|
|
||||||
|
-- DROP TABLE public.channel_videos;
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS public.channel_videos
|
||||||
|
(
|
||||||
|
id text NOT NULL,
|
||||||
|
title text,
|
||||||
|
published timestamp with time zone,
|
||||||
|
updated timestamp with time zone,
|
||||||
|
ucid text,
|
||||||
|
author text,
|
||||||
|
length_seconds integer,
|
||||||
|
live_now boolean,
|
||||||
|
premiere_timestamp timestamp with time zone,
|
||||||
|
views bigint,
|
||||||
|
CONSTRAINT channel_videos_id_key UNIQUE (id)
|
||||||
|
);
|
||||||
|
|
||||||
|
GRANT ALL ON TABLE public.channel_videos TO current_user;
|
||||||
|
|
||||||
|
-- Index: public.channel_videos_ucid_idx
|
||||||
|
|
||||||
|
-- DROP INDEX public.channel_videos_ucid_idx;
|
||||||
|
|
||||||
|
CREATE INDEX IF NOT EXISTS channel_videos_ucid_idx
|
||||||
|
ON public.channel_videos
|
||||||
|
USING btree
|
||||||
|
(ucid COLLATE pg_catalog."default");
|
||||||
|
|
||||||
25
stacks/invidious/config/sql/channels.sql
Normal file
25
stacks/invidious/config/sql/channels.sql
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
-- Table: public.channels
|
||||||
|
|
||||||
|
-- DROP TABLE public.channels;
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS public.channels
|
||||||
|
(
|
||||||
|
id text NOT NULL,
|
||||||
|
author text,
|
||||||
|
updated timestamp with time zone,
|
||||||
|
deleted boolean,
|
||||||
|
subscribed timestamp with time zone,
|
||||||
|
CONSTRAINT channels_id_key UNIQUE (id)
|
||||||
|
);
|
||||||
|
|
||||||
|
GRANT ALL ON TABLE public.channels TO current_user;
|
||||||
|
|
||||||
|
-- Index: public.channels_id_idx
|
||||||
|
|
||||||
|
-- DROP INDEX public.channels_id_idx;
|
||||||
|
|
||||||
|
CREATE INDEX IF NOT EXISTS channels_id_idx
|
||||||
|
ON public.channels
|
||||||
|
USING btree
|
||||||
|
(id COLLATE pg_catalog."default");
|
||||||
|
|
||||||
22
stacks/invidious/config/sql/nonces.sql
Normal file
22
stacks/invidious/config/sql/nonces.sql
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
-- Table: public.nonces
|
||||||
|
|
||||||
|
-- DROP TABLE public.nonces;
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS public.nonces
|
||||||
|
(
|
||||||
|
nonce text,
|
||||||
|
expire timestamp with time zone,
|
||||||
|
CONSTRAINT nonces_id_key UNIQUE (nonce)
|
||||||
|
);
|
||||||
|
|
||||||
|
GRANT ALL ON TABLE public.nonces TO current_user;
|
||||||
|
|
||||||
|
-- Index: public.nonces_nonce_idx
|
||||||
|
|
||||||
|
-- DROP INDEX public.nonces_nonce_idx;
|
||||||
|
|
||||||
|
CREATE INDEX IF NOT EXISTS nonces_nonce_idx
|
||||||
|
ON public.nonces
|
||||||
|
USING btree
|
||||||
|
(nonce COLLATE pg_catalog."default");
|
||||||
|
|
||||||
19
stacks/invidious/config/sql/playlist_videos.sql
Normal file
19
stacks/invidious/config/sql/playlist_videos.sql
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
-- Table: public.playlist_videos
|
||||||
|
|
||||||
|
-- DROP TABLE public.playlist_videos;
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS public.playlist_videos
|
||||||
|
(
|
||||||
|
title text,
|
||||||
|
id text,
|
||||||
|
author text,
|
||||||
|
ucid text,
|
||||||
|
length_seconds integer,
|
||||||
|
published timestamptz,
|
||||||
|
plid text references playlists(id),
|
||||||
|
index int8,
|
||||||
|
live_now boolean,
|
||||||
|
PRIMARY KEY (index,plid)
|
||||||
|
);
|
||||||
|
|
||||||
|
GRANT ALL ON TABLE public.playlist_videos TO current_user;
|
||||||
29
stacks/invidious/config/sql/playlists.sql
Normal file
29
stacks/invidious/config/sql/playlists.sql
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
-- Type: public.privacy
|
||||||
|
|
||||||
|
-- DROP TYPE public.privacy;
|
||||||
|
|
||||||
|
CREATE TYPE public.privacy AS ENUM
|
||||||
|
(
|
||||||
|
'Public',
|
||||||
|
'Unlisted',
|
||||||
|
'Private'
|
||||||
|
);
|
||||||
|
|
||||||
|
-- Table: public.playlists
|
||||||
|
|
||||||
|
-- DROP TABLE public.playlists;
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS public.playlists
|
||||||
|
(
|
||||||
|
title text,
|
||||||
|
id text primary key,
|
||||||
|
author text,
|
||||||
|
description text,
|
||||||
|
video_count integer,
|
||||||
|
created timestamptz,
|
||||||
|
updated timestamptz,
|
||||||
|
privacy privacy,
|
||||||
|
index int8[]
|
||||||
|
);
|
||||||
|
|
||||||
|
GRANT ALL ON public.playlists TO current_user;
|
||||||
23
stacks/invidious/config/sql/session_ids.sql
Normal file
23
stacks/invidious/config/sql/session_ids.sql
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
-- Table: public.session_ids
|
||||||
|
|
||||||
|
-- DROP TABLE public.session_ids;
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS public.session_ids
|
||||||
|
(
|
||||||
|
id text NOT NULL,
|
||||||
|
email text,
|
||||||
|
issued timestamp with time zone,
|
||||||
|
CONSTRAINT session_ids_pkey PRIMARY KEY (id)
|
||||||
|
);
|
||||||
|
|
||||||
|
GRANT ALL ON TABLE public.session_ids TO current_user;
|
||||||
|
|
||||||
|
-- Index: public.session_ids_id_idx
|
||||||
|
|
||||||
|
-- DROP INDEX public.session_ids_id_idx;
|
||||||
|
|
||||||
|
CREATE INDEX IF NOT EXISTS session_ids_id_idx
|
||||||
|
ON public.session_ids
|
||||||
|
USING btree
|
||||||
|
(id COLLATE pg_catalog."default");
|
||||||
|
|
||||||
29
stacks/invidious/config/sql/users.sql
Normal file
29
stacks/invidious/config/sql/users.sql
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
-- Table: public.users
|
||||||
|
|
||||||
|
-- DROP TABLE public.users;
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS public.users
|
||||||
|
(
|
||||||
|
updated timestamp with time zone,
|
||||||
|
notifications text[],
|
||||||
|
subscriptions text[],
|
||||||
|
email text NOT NULL,
|
||||||
|
preferences text,
|
||||||
|
password text,
|
||||||
|
token text,
|
||||||
|
watched text[],
|
||||||
|
feed_needs_update boolean,
|
||||||
|
CONSTRAINT users_email_key UNIQUE (email)
|
||||||
|
);
|
||||||
|
|
||||||
|
GRANT ALL ON TABLE public.users TO current_user;
|
||||||
|
|
||||||
|
-- Index: public.email_unique_idx
|
||||||
|
|
||||||
|
-- DROP INDEX public.email_unique_idx;
|
||||||
|
|
||||||
|
CREATE UNIQUE INDEX IF NOT EXISTS email_unique_idx
|
||||||
|
ON public.users
|
||||||
|
USING btree
|
||||||
|
(lower(email) COLLATE pg_catalog."default");
|
||||||
|
|
||||||
23
stacks/invidious/config/sql/videos.sql
Normal file
23
stacks/invidious/config/sql/videos.sql
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
-- Table: public.videos
|
||||||
|
|
||||||
|
-- DROP TABLE public.videos;
|
||||||
|
|
||||||
|
CREATE UNLOGGED TABLE IF NOT EXISTS public.videos
|
||||||
|
(
|
||||||
|
id text NOT NULL,
|
||||||
|
info text,
|
||||||
|
updated timestamp with time zone,
|
||||||
|
CONSTRAINT videos_pkey PRIMARY KEY (id)
|
||||||
|
);
|
||||||
|
|
||||||
|
GRANT ALL ON TABLE public.videos TO current_user;
|
||||||
|
|
||||||
|
-- Index: public.id_idx
|
||||||
|
|
||||||
|
-- DROP INDEX public.id_idx;
|
||||||
|
|
||||||
|
CREATE UNIQUE INDEX IF NOT EXISTS id_idx
|
||||||
|
ON public.videos
|
||||||
|
USING btree
|
||||||
|
(id COLLATE pg_catalog."default");
|
||||||
|
|
||||||
@@ -1,10 +1,8 @@
|
|||||||
services:
|
services:
|
||||||
invidious:
|
invidious:
|
||||||
image: quay.io/invidious/invidious:latest
|
image: quay.io/invidious/invidious:master
|
||||||
container_name: invidious
|
container_name: invidious
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
ports:
|
|
||||||
- "3001:3000"
|
|
||||||
environment:
|
environment:
|
||||||
INVIDIOUS_CONFIG: |
|
INVIDIOUS_CONFIG: |
|
||||||
db:
|
db:
|
||||||
@@ -14,45 +12,96 @@ services:
|
|||||||
host: invidious-db
|
host: invidious-db
|
||||||
port: 5432
|
port: 5432
|
||||||
check_tables: true
|
check_tables: true
|
||||||
signature_server: inv_sig_helper:12999
|
invidious_companion:
|
||||||
visitor_data: ${INVIDIOUS_VISITOR_DATA}
|
- private_url: "http://invidious-companion:8282/companion"
|
||||||
po_token: ${INVIDIOUS_PO_TOKEN}
|
public_url: "https://inv.${DOMAIN}"
|
||||||
|
invidious_companion_key: "${INVIDIOUS_COMPANION_KEY}"
|
||||||
|
external_port: 443
|
||||||
|
domain: inv.${DOMAIN}
|
||||||
|
https_only: true
|
||||||
hmac_key: "${INVIDIOUS_HMAC_KEY}"
|
hmac_key: "${INVIDIOUS_HMAC_KEY}"
|
||||||
|
hsts: false
|
||||||
|
log_level: Info
|
||||||
|
healthcheck:
|
||||||
|
test: wget -nv --tries=1 --spider "http://127.0.0.1:3000/api/v1/search?q=test" || exit 1
|
||||||
|
interval: 30s
|
||||||
|
timeout: 5s
|
||||||
|
retries: 2
|
||||||
logging:
|
logging:
|
||||||
options:
|
options:
|
||||||
max-size: "1G"
|
max-size: "1G"
|
||||||
max-file: "4"
|
max-file: "4"
|
||||||
depends_on:
|
depends_on:
|
||||||
- invidious-db
|
- invidious-db
|
||||||
|
deploy:
|
||||||
|
resources:
|
||||||
|
limits:
|
||||||
|
cpus: '1'
|
||||||
|
memory: 2G
|
||||||
labels:
|
labels:
|
||||||
|
- "com.ghost.tel/stack-type=public"
|
||||||
- "traefik.enable=true"
|
- "traefik.enable=true"
|
||||||
- "traefik.http.services.invidious.loadbalancer.server.port=3000"
|
- "traefik.http.services.invid.loadbalancer.server.port=3000"
|
||||||
- "traefik.http.routers.invidious.entrypoints=https"
|
- "traefik.http.routers.invid.entrypoints=http,https"
|
||||||
- "traefik.http.routers.invidious.rule=Host(`invid.${DOMAIN}`, `i.${DOMAIN}`)"
|
- "traefik.http.routers.invid.rule=Host(`inv.${DOMAIN}`) && !(Path(`/latest_version`) || PathPrefix(`/api/manifest/dash/id/`) || PathPrefix(`/videoplayback`) || PathPrefix(`/download`))"
|
||||||
- "traefik.http.routers.invidious.tls.certresolver=http"
|
- "traefik.http.routers.invid.tls.certresolver=http"
|
||||||
networks:
|
networks:
|
||||||
- web
|
- web
|
||||||
- default
|
- default
|
||||||
|
|
||||||
inv_sig_helper:
|
invidious-companion:
|
||||||
image: quay.io/invidious/inv-sig-helper:latest
|
image: quay.io/invidious/invidious-companion:latest
|
||||||
container_name: inv-sig-helper
|
container_name: invidious-companion
|
||||||
command: ["--tcp", "0.0.0.0:12999"]
|
|
||||||
environment:
|
|
||||||
- RUST_LOG=info
|
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
|
environment:
|
||||||
|
- SERVER_SECRET_KEY=${INVIDIOUS_COMPANION_KEY}
|
||||||
|
- SERVER_BASE_URL=https://inv.${DOMAIN}/companion
|
||||||
|
logging:
|
||||||
|
options:
|
||||||
|
max-size: "1G"
|
||||||
|
max-file: "4"
|
||||||
cap_drop:
|
cap_drop:
|
||||||
- ALL
|
- ALL
|
||||||
read_only: true
|
read_only: true
|
||||||
|
volumes:
|
||||||
|
- companion-cache:/var/tmp/youtubei.js:rw
|
||||||
security_opt:
|
security_opt:
|
||||||
- no-new-privileges:true
|
- no-new-privileges:true
|
||||||
|
deploy:
|
||||||
|
resources:
|
||||||
|
limits:
|
||||||
|
cpus: '0.5'
|
||||||
|
memory: 1G
|
||||||
|
labels:
|
||||||
|
- "traefik.enable=true"
|
||||||
|
- "traefik.http.services.invid-companion.loadbalancer.server.port=8282"
|
||||||
|
- "traefik.http.routers.invid-companion.entrypoints=http,https"
|
||||||
|
- "traefik.http.routers.invid-companion.rule=Host(`inv.${DOMAIN}`) && (Path(`/latest_version`) || PathPrefix(`/api/manifest/dash/id/`) || PathPrefix(`/youtubei/v1/player`) || PathPrefix(`/videoplayback`) || PathPrefix(`/download`))"
|
||||||
|
- "traefik.http.routers.invid-companion.tls.certresolver=http"
|
||||||
|
- "traefik.http.routers.invid-companion.middlewares=invid-companion-prefix@docker"
|
||||||
|
networks:
|
||||||
|
- web
|
||||||
|
- default
|
||||||
|
|
||||||
|
invidious-restarter:
|
||||||
|
image: docker:cli
|
||||||
|
container_name: invidious-restarter
|
||||||
|
restart: unless-stopped
|
||||||
|
volumes:
|
||||||
|
- /var/run/docker.sock:/var/run/docker.sock
|
||||||
|
command: sh -c "while true; do sleep 3600; docker restart invidious invidious-companion; done"
|
||||||
|
deploy:
|
||||||
|
resources:
|
||||||
|
limits:
|
||||||
|
cpus: '0.1'
|
||||||
|
memory: 32M
|
||||||
|
|
||||||
invidious-db:
|
invidious-db:
|
||||||
image: postgres:14
|
image: postgres:14
|
||||||
container_name: invidious-db
|
container_name: invidious-db
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
volumes:
|
volumes:
|
||||||
- ./postgres:/var/lib/postgresql/data
|
- postgres-data:/var/lib/postgresql/data
|
||||||
- ./config/sql:/config/sql
|
- ./config/sql:/config/sql
|
||||||
- ./docker/init-invidious-db.sh:/docker-entrypoint-initdb.d/init-invidious-db.sh
|
- ./docker/init-invidious-db.sh:/docker-entrypoint-initdb.d/init-invidious-db.sh
|
||||||
environment:
|
environment:
|
||||||
@@ -61,6 +110,15 @@ services:
|
|||||||
POSTGRES_PASSWORD: ${INVIDIOUS_DB_PASSWORD}
|
POSTGRES_PASSWORD: ${INVIDIOUS_DB_PASSWORD}
|
||||||
healthcheck:
|
healthcheck:
|
||||||
test: ["CMD-SHELL", "pg_isready -U $$POSTGRES_USER -d $$POSTGRES_DB"]
|
test: ["CMD-SHELL", "pg_isready -U $$POSTGRES_USER -d $$POSTGRES_DB"]
|
||||||
|
deploy:
|
||||||
|
resources:
|
||||||
|
limits:
|
||||||
|
cpus: '0.5'
|
||||||
|
memory: 1G
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
postgres-data:
|
||||||
|
companion-cache:
|
||||||
|
|
||||||
networks:
|
networks:
|
||||||
web:
|
web:
|
||||||
|
|||||||
12
stacks/invidious/docker/init-invidious-db.sh
Executable file
12
stacks/invidious/docker/init-invidious-db.sh
Executable file
@@ -0,0 +1,12 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -eou pipefail
|
||||||
|
|
||||||
|
psql --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" < config/sql/channels.sql
|
||||||
|
psql --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" < config/sql/videos.sql
|
||||||
|
psql --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" < config/sql/channel_videos.sql
|
||||||
|
psql --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" < config/sql/users.sql
|
||||||
|
psql --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" < config/sql/session_ids.sql
|
||||||
|
psql --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" < config/sql/nonces.sql
|
||||||
|
psql --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" < config/sql/annotations.sql
|
||||||
|
psql --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" < config/sql/playlists.sql
|
||||||
|
psql --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" < config/sql/playlist_videos.sql
|
||||||
2
stacks/matomo-public/.env.template
Normal file
2
stacks/matomo-public/.env.template
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
MATOMO_MYSQL_ROOT_PASSWORD=changeme
|
||||||
|
MATOMO_MYSQL_PASSWORD=changeme
|
||||||
50
stacks/matomo-public/docker-compose.yml
Normal file
50
stacks/matomo-public/docker-compose.yml
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
services:
|
||||||
|
db:
|
||||||
|
image: mariadb:latest
|
||||||
|
container_name: matomo-db
|
||||||
|
restart: unless-stopped
|
||||||
|
labels:
|
||||||
|
- "com.ghost.tel/stack-type=public"
|
||||||
|
command: --max-allowed-packet=64MB
|
||||||
|
environment:
|
||||||
|
MYSQL_ROOT_PASSWORD: ${MATOMO_MYSQL_ROOT_PASSWORD}
|
||||||
|
MYSQL_DATABASE: matomo
|
||||||
|
MYSQL_USER: matomo
|
||||||
|
MYSQL_PASSWORD: ${MATOMO_MYSQL_PASSWORD}
|
||||||
|
volumes:
|
||||||
|
- ./mysql:/var/lib/mysql
|
||||||
|
|
||||||
|
app:
|
||||||
|
image: matomo:latest
|
||||||
|
container_name: matomo
|
||||||
|
restart: unless-stopped
|
||||||
|
labels:
|
||||||
|
- "com.ghost.tel/stack-type=public"
|
||||||
|
- "traefik.enable=true"
|
||||||
|
- "traefik.http.routers.matomo.entrypoints=https"
|
||||||
|
- "traefik.http.routers.matomo.rule=Host(`matomo.sequela.tel`)"
|
||||||
|
- "traefik.http.routers.matomo.tls.certresolver=http"
|
||||||
|
- "traefik.http.services.matomo.loadbalancer.server.port=80"
|
||||||
|
environment:
|
||||||
|
MATOMO_DATABASE_HOST: db
|
||||||
|
MATOMO_DATABASE_ADAPTER: mysql
|
||||||
|
MATOMO_DATABASE_TABLES_PREFIX: matomo_
|
||||||
|
MATOMO_DATABASE_USERNAME: matomo
|
||||||
|
MATOMO_DATABASE_PASSWORD: ${MATOMO_MYSQL_PASSWORD}
|
||||||
|
MATOMO_DATABASE_DBNAME: matomo
|
||||||
|
volumes:
|
||||||
|
- matomo-data:/var/www/html
|
||||||
|
expose:
|
||||||
|
- "80"
|
||||||
|
depends_on:
|
||||||
|
- db
|
||||||
|
networks:
|
||||||
|
- web
|
||||||
|
- default
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
matomo-data:
|
||||||
|
|
||||||
|
networks:
|
||||||
|
web:
|
||||||
|
external: true
|
||||||
@@ -11,6 +11,7 @@ services:
|
|||||||
- web
|
- web
|
||||||
- default
|
- default
|
||||||
labels:
|
labels:
|
||||||
|
- "com.ghost.tel/stack-type=prod"
|
||||||
- "traefik.enable=true"
|
- "traefik.enable=true"
|
||||||
- "traefik.http.routers.memento.entrypoints=https"
|
- "traefik.http.routers.memento.entrypoints=https"
|
||||||
- "traefik.http.routers.memento.rule=Host(`memento.${DOMAIN}`)"
|
- "traefik.http.routers.memento.rule=Host(`memento.${DOMAIN}`)"
|
||||||
|
|||||||
@@ -2,6 +2,8 @@ services:
|
|||||||
meshmonitor:
|
meshmonitor:
|
||||||
image: ghcr.io/yeraze/meshmonitor:latest
|
image: ghcr.io/yeraze/meshmonitor:latest
|
||||||
container_name: meshmonitor
|
container_name: meshmonitor
|
||||||
|
labels:
|
||||||
|
- "com.ghost.tel/stack-type=dev-only"
|
||||||
ports:
|
ports:
|
||||||
- "8383:3001"
|
- "8383:3001"
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
|
|||||||
@@ -3,5 +3,7 @@ services:
|
|||||||
image: ghcr.io/meshtastic/web:latest
|
image: ghcr.io/meshtastic/web:latest
|
||||||
container_name: meshtastic-web
|
container_name: meshtastic-web
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
|
labels:
|
||||||
|
- "com.ghost.tel/stack-type=dev-only"
|
||||||
ports:
|
ports:
|
||||||
- "8585:8080"
|
- "8585:8080"
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
version: "3.9"
|
|
||||||
|
|
||||||
services:
|
services:
|
||||||
grafana-alert-webhook:
|
grafana-alert-webhook:
|
||||||
build: .
|
build: .
|
||||||
|
labels:
|
||||||
|
- "com.ghost.tel/stack-type=dev-only"
|
||||||
env_file:
|
env_file:
|
||||||
- .env
|
- .env
|
||||||
ports:
|
ports:
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
version: "3.9"
|
|
||||||
|
|
||||||
services:
|
services:
|
||||||
frontend:
|
frontend:
|
||||||
build:
|
build:
|
||||||
context: .
|
context: .
|
||||||
dockerfile: frontend/Dockerfile
|
dockerfile: frontend/Dockerfile
|
||||||
restart: always
|
restart: always
|
||||||
|
labels:
|
||||||
|
- "com.ghost.tel/stack-type=dev-only"
|
||||||
env_file:
|
env_file:
|
||||||
- .env
|
- .env
|
||||||
environment:
|
environment:
|
||||||
|
|||||||
@@ -3,6 +3,8 @@ services:
|
|||||||
obsidian:
|
obsidian:
|
||||||
image: lscr.io/linuxserver/obsidian:latest
|
image: lscr.io/linuxserver/obsidian:latest
|
||||||
container_name: obsidian
|
container_name: obsidian
|
||||||
|
labels:
|
||||||
|
- "com.ghost.tel/stack-type=dev-only"
|
||||||
security_opt:
|
security_opt:
|
||||||
- seccomp:unconfined #optional
|
- seccomp:unconfined #optional
|
||||||
environment:
|
environment:
|
||||||
@@ -14,7 +16,5 @@ services:
|
|||||||
ports:
|
ports:
|
||||||
- 3002:3000
|
- 3002:3000
|
||||||
- 3003:3001
|
- 3003:3001
|
||||||
devices:
|
|
||||||
- /dev/dri:/dev/dri #optional
|
|
||||||
shm_size: "1gb"
|
shm_size: "1gb"
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
|
|||||||
@@ -18,12 +18,13 @@ services:
|
|||||||
depends_on:
|
depends_on:
|
||||||
- syncthing
|
- syncthing
|
||||||
labels:
|
labels:
|
||||||
|
- "com.ghost.tel/stack-type=dev-only"
|
||||||
- "traefik.enable=true"
|
- "traefik.enable=true"
|
||||||
- "traefik.docker.network=web"
|
- "traefik.docker.network=web"
|
||||||
- "traefik.http.routers.todo-obbytodo.entrypoints=https"
|
- "traefik.http.routers.todo-obbytodo.entrypoints=https"
|
||||||
- "traefik.http.routers.todo-obbytodo.rule=Host(`shell.${DOMAIN}`) && PathPrefix(`/todo`)"
|
- "traefik.http.routers.todo-obbytodo.rule=Host(`shell.${DOMAIN}`) && PathPrefix(`/todo`)"
|
||||||
- "traefik.http.routers.todo-obbytodo.tls.certresolver=http"
|
- "traefik.http.routers.todo-obbytodo.tls.certresolver=http"
|
||||||
- "traefik.http.routers.todo-obbytodo.middlewares=todo-obbytodo-stripprefix@docker,dashboard-auth@file"
|
- "traefik.http.routers.todo-obbytodo.middlewares=todo-obbytodo-stripprefix@docker,dashboard-auth@docker"
|
||||||
- "traefik.http.routers.todo-obbytodo.priority=100"
|
- "traefik.http.routers.todo-obbytodo.priority=100"
|
||||||
- "traefik.http.middlewares.todo-obbytodo-stripprefix.stripPrefix.prefixes=/todo"
|
- "traefik.http.middlewares.todo-obbytodo-stripprefix.stripPrefix.prefixes=/todo"
|
||||||
- "traefik.http.services.todo-obbytodo.loadbalancer.server.port=3000"
|
- "traefik.http.services.todo-obbytodo.loadbalancer.server.port=3000"
|
||||||
@@ -31,7 +32,7 @@ services:
|
|||||||
- "traefik.http.routers.events-obbytodo.entrypoints=https"
|
- "traefik.http.routers.events-obbytodo.entrypoints=https"
|
||||||
- "traefik.http.routers.events-obbytodo.rule=Host(`shell.${DOMAIN}`) && PathPrefix(`/events`)"
|
- "traefik.http.routers.events-obbytodo.rule=Host(`shell.${DOMAIN}`) && PathPrefix(`/events`)"
|
||||||
- "traefik.http.routers.events-obbytodo.tls.certresolver=http"
|
- "traefik.http.routers.events-obbytodo.tls.certresolver=http"
|
||||||
- "traefik.http.routers.events-obbytodo.middlewares=dashboard-auth@file"
|
- "traefik.http.routers.events-obbytodo.middlewares=dashboard-auth@docker"
|
||||||
- "traefik.http.routers.events-obbytodo.priority=100"
|
- "traefik.http.routers.events-obbytodo.priority=100"
|
||||||
- "traefik.http.routers.events-obbytodo.service=todo-obbytodo"
|
- "traefik.http.routers.events-obbytodo.service=todo-obbytodo"
|
||||||
|
|
||||||
@@ -52,13 +53,18 @@ services:
|
|||||||
- syncthing
|
- syncthing
|
||||||
networks:
|
networks:
|
||||||
- web
|
- web
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD-SHELL", "wget -qO- 'http://127.0.0.1:3001/api/search?q=test' >/dev/null 2>&1 || exit 1"]
|
||||||
|
interval: 30s
|
||||||
|
timeout: 5s
|
||||||
|
retries: 3
|
||||||
labels:
|
labels:
|
||||||
- "traefik.enable=true"
|
- "traefik.enable=true"
|
||||||
- "traefik.docker.network=web"
|
- "traefik.docker.network=web"
|
||||||
- "traefik.http.routers.shell-secure.entrypoints=https"
|
- "traefik.http.routers.shell-secure.entrypoints=https"
|
||||||
- "traefik.http.routers.shell-secure.rule=Host(`shell.${DOMAIN}`)"
|
- "traefik.http.routers.shell-secure.rule=Host(`shell.${DOMAIN}`)"
|
||||||
- "traefik.http.routers.shell-secure.tls.certresolver=http"
|
- "traefik.http.routers.shell-secure.tls.certresolver=http"
|
||||||
- "traefik.http.routers.shell-secure.middlewares=dashboard-auth@file"
|
- "traefik.http.routers.shell-secure.middlewares=dashboard-auth@docker"
|
||||||
- "traefik.http.services.shell-secure.loadbalancer.server.port=3033"
|
- "traefik.http.services.shell-secure.loadbalancer.server.port=3033"
|
||||||
- "traefik.http.routers.shell-secure.service=shell-secure"
|
- "traefik.http.routers.shell-secure.service=shell-secure"
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
FROM node:18-alpine
|
FROM node:18-alpine
|
||||||
|
RUN apk add --no-cache python3 make g++ vips-dev fontconfig ttf-dejavu
|
||||||
WORKDIR /usr/src/app
|
WORKDIR /usr/src/app
|
||||||
COPY package.json ./
|
COPY content/package.json ./
|
||||||
RUN npm install
|
RUN npm install
|
||||||
COPY server.js ./
|
|
||||||
EXPOSE 3000
|
EXPOSE 3000
|
||||||
CMD ["node", "server.js"]
|
CMD ["node", "content/server.js"]
|
||||||
|
|||||||
@@ -3,40 +3,45 @@ services:
|
|||||||
build: .
|
build: .
|
||||||
container_name: perilous-web
|
container_name: perilous-web
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
ports:
|
expose:
|
||||||
- "3003:3000"
|
- "3000"
|
||||||
volumes:
|
volumes:
|
||||||
- ./content:/usr/src/app/content
|
- ./content:/usr/src/app/content
|
||||||
labels:
|
environment:
|
||||||
- "traefik.enable=true"
|
- EMAIL_PASSWORD=${PERILOUS_CODE_SERVER_PASSWORD}
|
||||||
- "traefik.http.routers.perilous-secure.entrypoints=https,http"
|
|
||||||
- "traefik.http.routers.perilous-secure.rule=Host(`chapel.perilous.dev`,`forest.perilous.dev`,`castle.perilous.dev`,`siege.perilous.dev`,`pass.perilous.dev`,`perilous.dev`,`www.perilous.dev`,`word.perilous.dev`,`mirror.perilous.dev`,`request.perilous.dev`,`the.chapel.perilous.dev`,`the.forest.perilous.dev`,`the.castle.perilous.dev`,`the.siege.perilous.dev`,`the.pass.perilous.dev`,`the.word.perilous.dev`,`the.mirror.perilous.dev`,`the.request.perilous.dev`,`the.adventure.perilous.dev`,`the.cs.perilous.dev`,`the.gallery.perilous.dev`,`gallery.perilous.dev`,`the.perilous.dev`,`ring.perilous.dev`,`the.ring.perilous.dev`,`autumn.perilous.dev`,`the.autumn.perilous.dev`)"
|
|
||||||
- "traefik.http.routers.perilous-secure.tls.certresolver=http"
|
|
||||||
networks:
|
networks:
|
||||||
- web
|
- web
|
||||||
|
labels:
|
||||||
|
- "com.ghost.tel/stack-type=prod"
|
||||||
|
- "traefik.enable=true"
|
||||||
|
- "traefik.http.routers.perilous.entrypoints=https"
|
||||||
|
- "traefik.http.routers.perilous.rule=Host(`perilous.dev`) || Host(`www.perilous.dev`) || HostRegexp(`^.+\\.perilous\\.dev$$`)"
|
||||||
|
- "traefik.http.routers.perilous.tls.certresolver=http"
|
||||||
|
- "traefik.http.services.perilous.loadbalancer.server.port=3000"
|
||||||
|
|
||||||
code-server:
|
code-server:
|
||||||
image: lscr.io/linuxserver/code-server:latest
|
image: lscr.io/linuxserver/code-server:latest
|
||||||
container_name: perilous-code-server
|
container_name: perilous-code-server
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
|
expose:
|
||||||
|
- "8443"
|
||||||
volumes:
|
volumes:
|
||||||
- ./content:/home/project
|
- ./content:/home/project
|
||||||
- ./config:/config
|
- ./config:/config
|
||||||
ports:
|
|
||||||
- "8180:8443"
|
|
||||||
environment:
|
environment:
|
||||||
- PASSWORD=${PERILOUS_CODE_SERVER_PASSWORD}
|
- PASSWORD=${PERILOUS_CODE_SERVER_PASSWORD}
|
||||||
- PUID=1000
|
- PUID=1000
|
||||||
- PGID=1000
|
- PGID=1000
|
||||||
- PROXY_DOMAIN=cs.perilous.dev
|
- PROXY_DOMAIN=cs.perilous.dev
|
||||||
- DEFAULT_WORKSPACE=/home/project
|
- DEFAULT_WORKSPACE=/home/project
|
||||||
labels:
|
|
||||||
- "traefik.enable=true"
|
|
||||||
- "traefik.http.routers.pcs-secure.entrypoints=https,http"
|
|
||||||
- "traefik.http.routers.pcs-secure.rule=Host(`cs.perilous.dev`)"
|
|
||||||
- "traefik.http.routers.pcs-secure.tls.certresolver=http"
|
|
||||||
networks:
|
networks:
|
||||||
- web
|
- web
|
||||||
|
labels:
|
||||||
|
- "traefik.enable=true"
|
||||||
|
- "traefik.http.routers.perilous-cs.entrypoints=https"
|
||||||
|
- "traefik.http.routers.perilous-cs.rule=Host(`cs.perilous.dev`)"
|
||||||
|
- "traefik.http.routers.perilous-cs.tls.certresolver=http"
|
||||||
|
- "traefik.http.services.perilous-cs.loadbalancer.server.port=8443"
|
||||||
|
|
||||||
networks:
|
networks:
|
||||||
web:
|
web:
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ services:
|
|||||||
volumes:
|
volumes:
|
||||||
- ./data:/data
|
- ./data:/data
|
||||||
labels:
|
labels:
|
||||||
|
- "com.ghost.tel/stack-type=prod"
|
||||||
- "traefik.enable=true"
|
- "traefik.enable=true"
|
||||||
- "traefik.http.routers.radicale.entrypoints=https"
|
- "traefik.http.routers.radicale.entrypoints=https"
|
||||||
- "traefik.http.routers.radicale.rule=Host(`radicale.${DOMAIN}`)"
|
- "traefik.http.routers.radicale.rule=Host(`radicale.${DOMAIN}`)"
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ services:
|
|||||||
networks:
|
networks:
|
||||||
- web
|
- web
|
||||||
labels:
|
labels:
|
||||||
|
- "com.ghost.tel/stack-type=prod"
|
||||||
- "traefik.enable=true"
|
- "traefik.enable=true"
|
||||||
- "traefik.http.routers.ramz-secure.entrypoints=https,http"
|
- "traefik.http.routers.ramz-secure.entrypoints=https,http"
|
||||||
- "traefik.http.routers.ramz-secure.rule=Host(`parker.ramz.cc`)"
|
- "traefik.http.routers.ramz-secure.rule=Host(`parker.ramz.cc`)"
|
||||||
|
|||||||
@@ -3,25 +3,45 @@ services:
|
|||||||
image: registry:2
|
image: registry:2
|
||||||
container_name: registry
|
container_name: registry
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
volumes:
|
|
||||||
- ./data:/var/lib/registry
|
|
||||||
- ./auth:/auth
|
|
||||||
environment:
|
|
||||||
REGISTRY_AUTH: htpasswd
|
|
||||||
REGISTRY_AUTH_HTPASSWD_REALM: Registry Realm
|
|
||||||
REGISTRY_AUTH_HTPASSWD_PATH: /auth/htpasswd
|
|
||||||
REGISTRY_HTTP_SECRET: ${REGISTRY_HTTP_SECRET}
|
|
||||||
expose:
|
expose:
|
||||||
- 5000
|
- "5000"
|
||||||
|
volumes:
|
||||||
|
- ./docker:/var/lib/registry
|
||||||
networks:
|
networks:
|
||||||
- web
|
- web
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "wget", "--spider", "localhost:5000/v2/"]
|
||||||
|
interval: 60s
|
||||||
|
timeout: 10s
|
||||||
labels:
|
labels:
|
||||||
|
- "com.ghost.tel/stack-type=prod"
|
||||||
- "traefik.enable=true"
|
- "traefik.enable=true"
|
||||||
- "traefik.http.routers.registry.entrypoints=https"
|
- "traefik.http.routers.registry.entrypoints=https"
|
||||||
- "traefik.http.routers.registry.rule=Host(`registry.${DOMAIN}`)"
|
- "traefik.http.routers.registry.rule=Host(`registry.${DOMAIN}`)"
|
||||||
- "traefik.http.routers.registry.tls.certresolver=http"
|
- "traefik.http.routers.registry.tls.certresolver=http"
|
||||||
- "traefik.http.services.registry.loadbalancer.server.port=5000"
|
- "traefik.http.services.registry.loadbalancer.server.port=5000"
|
||||||
|
|
||||||
|
registry-ui:
|
||||||
|
image: quiq/docker-registry-ui:latest
|
||||||
|
container_name: registry-ui
|
||||||
|
restart: unless-stopped
|
||||||
|
expose:
|
||||||
|
- "8000"
|
||||||
|
volumes:
|
||||||
|
- ./registry-ui:/opt/data
|
||||||
|
- ./registry-ui.yml:/opt/config.yml:ro
|
||||||
|
depends_on:
|
||||||
|
registry:
|
||||||
|
condition: service_healthy
|
||||||
|
networks:
|
||||||
|
- web
|
||||||
|
labels:
|
||||||
|
- "traefik.enable=true"
|
||||||
|
- "traefik.http.routers.registry-ui.entrypoints=https"
|
||||||
|
- "traefik.http.routers.registry-ui.rule=Host(`dockerhub.${DOMAIN}`)"
|
||||||
|
- "traefik.http.routers.registry-ui.tls.certresolver=http"
|
||||||
|
- "traefik.http.services.registry-ui.loadbalancer.server.port=8000"
|
||||||
|
|
||||||
networks:
|
networks:
|
||||||
web:
|
web:
|
||||||
external: true
|
external: true
|
||||||
|
|||||||
22
stacks/rsshub-public/docker-compose.yml
Normal file
22
stacks/rsshub-public/docker-compose.yml
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
services:
|
||||||
|
rsshub:
|
||||||
|
image: diygod/rsshub:latest
|
||||||
|
container_name: rsshub
|
||||||
|
restart: unless-stopped
|
||||||
|
labels:
|
||||||
|
- "com.ghost.tel/stack-type=public"
|
||||||
|
- "traefik.enable=true"
|
||||||
|
- "traefik.http.routers.rsshub.entrypoints=https"
|
||||||
|
- "traefik.http.routers.rsshub.rule=Host(`rsshub.uplink.tel`)"
|
||||||
|
- "traefik.http.routers.rsshub.tls.certresolver=http"
|
||||||
|
- "traefik.http.services.rsshub.loadbalancer.server.port=1200"
|
||||||
|
environment:
|
||||||
|
- CACHE_EXPIRE=3600
|
||||||
|
expose:
|
||||||
|
- "1200"
|
||||||
|
networks:
|
||||||
|
- web
|
||||||
|
|
||||||
|
networks:
|
||||||
|
web:
|
||||||
|
external: true
|
||||||
54
stacks/searx-public/docker-compose.yml
Normal file
54
stacks/searx-public/docker-compose.yml
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
services:
|
||||||
|
redis:
|
||||||
|
image: redis:alpine
|
||||||
|
container_name: searx-redis
|
||||||
|
restart: unless-stopped
|
||||||
|
command: redis-server --save "" --appendonly "no"
|
||||||
|
tmpfs:
|
||||||
|
- /var/lib/redis
|
||||||
|
cap_drop:
|
||||||
|
- ALL
|
||||||
|
cap_add:
|
||||||
|
- SETGID
|
||||||
|
- SETUID
|
||||||
|
- DAC_OVERRIDE
|
||||||
|
networks:
|
||||||
|
- default
|
||||||
|
|
||||||
|
searxng:
|
||||||
|
image: searxng/searxng:latest
|
||||||
|
container_name: searxng
|
||||||
|
restart: unless-stopped
|
||||||
|
labels:
|
||||||
|
- "com.ghost.tel/stack-type=public"
|
||||||
|
- "traefik.enable=true"
|
||||||
|
- "traefik.http.routers.searx.entrypoints=https"
|
||||||
|
- "traefik.http.routers.searx.rule=Host(`searx.uplink.tel`)"
|
||||||
|
- "traefik.http.routers.searx.tls.certresolver=http"
|
||||||
|
- "traefik.http.services.searx.loadbalancer.server.port=8080"
|
||||||
|
environment:
|
||||||
|
- SEARXNG_BASE_URL=https://searx.uplink.tel/
|
||||||
|
volumes:
|
||||||
|
- ./config:/etc/searxng:rw
|
||||||
|
expose:
|
||||||
|
- "8080"
|
||||||
|
cap_drop:
|
||||||
|
- ALL
|
||||||
|
cap_add:
|
||||||
|
- CHOWN
|
||||||
|
- SETGID
|
||||||
|
- SETUID
|
||||||
|
logging:
|
||||||
|
driver: "json-file"
|
||||||
|
options:
|
||||||
|
max-size: "1m"
|
||||||
|
max-file: "1"
|
||||||
|
depends_on:
|
||||||
|
- redis
|
||||||
|
networks:
|
||||||
|
- web
|
||||||
|
- default
|
||||||
|
|
||||||
|
networks:
|
||||||
|
web:
|
||||||
|
external: true
|
||||||
24
stacks/service-map/docker-compose.yml
Normal file
24
stacks/service-map/docker-compose.yml
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
services:
|
||||||
|
service-map:
|
||||||
|
build: .
|
||||||
|
container_name: service-map
|
||||||
|
restart: unless-stopped
|
||||||
|
labels:
|
||||||
|
- "com.ghost.tel/stack-type=dev-only"
|
||||||
|
- "traefik.enable=true"
|
||||||
|
- "traefik.http.routers.service-map.rule=Host(`map.ghost.tel`)"
|
||||||
|
- "traefik.http.routers.service-map.entrypoints=https"
|
||||||
|
- "traefik.http.routers.service-map.tls.certresolver=http"
|
||||||
|
- "traefik.http.routers.service-map.middlewares=dashboard-auth@docker"
|
||||||
|
- "traefik.http.services.service-map.loadbalancer.server.port=3000"
|
||||||
|
environment:
|
||||||
|
- HOSTS=ubuntu-dev,ubuntu-prod
|
||||||
|
volumes:
|
||||||
|
- /var/run/docker.sock:/var/run/docker.sock:ro
|
||||||
|
- ~/.ssh:/root/.ssh:ro
|
||||||
|
networks:
|
||||||
|
- web
|
||||||
|
|
||||||
|
networks:
|
||||||
|
web:
|
||||||
|
external: true
|
||||||
@@ -15,11 +15,12 @@ services:
|
|||||||
networks:
|
networks:
|
||||||
- web
|
- web
|
||||||
labels:
|
labels:
|
||||||
|
- "com.ghost.tel/stack-type=prod"
|
||||||
- "org.opencontainers.image.source=https://gitea.ghost.tel/knight/docker-stacks"
|
- "org.opencontainers.image.source=https://gitea.ghost.tel/knight/docker-stacks"
|
||||||
- "com.centurylinklabs.watchtower.enable=true"
|
- "com.centurylinklabs.watchtower.enable=true"
|
||||||
- "traefik.enable=true"
|
- "traefik.enable=true"
|
||||||
- "traefik.http.routers.smokeping.entrypoints=https"
|
- "traefik.http.routers.smokeping.entrypoints=https"
|
||||||
- "traefik.http.routers.smokeping.rule=Host(`smokeping.${DOMAIN}`)"
|
- "traefik.http.routers.smokeping.rule=Host(`smoke.${DOMAIN}`)"
|
||||||
- "traefik.http.routers.smokeping.tls.certresolver=http"
|
- "traefik.http.routers.smokeping.tls.certresolver=http"
|
||||||
- "traefik.http.services.smokeping.loadbalancer.server.port=80"
|
- "traefik.http.services.smokeping.loadbalancer.server.port=80"
|
||||||
|
|
||||||
|
|||||||
@@ -1,15 +1,11 @@
|
|||||||
services:
|
services:
|
||||||
snowflake-proxy:
|
snowflake-proxy:
|
||||||
network_mode: host
|
network_mode: host
|
||||||
image: containers.torproject.org/tpo/anti-censorship/pluggable-transports/snowflake:latest
|
image: containers.torproject.org/tpo/anti-censorship/pluggable-transports/snowflake:latest
|
||||||
container_name: snowflake-proxy
|
container_name: snowflake-proxy
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
# For a full list of Snowflake Proxy CLI parameters see
|
labels:
|
||||||
# https://gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/snowflake/-/tree/main/proxy?ref_type=heads#running-a-standalone-snowflake-proxy
|
- "com.ghost.tel/stack-type=public"
|
||||||
#command: [ "-ephemeral-ports-range", "30000:60000" ]
|
# For a full list of Snowflake Proxy CLI parameters see
|
||||||
watchtower:
|
# https://gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/snowflake/-/tree/main/proxy?ref_type=heads#running-a-standalone-snowflake-proxy
|
||||||
image: containrrr/watchtower
|
#command: [ "-ephemeral-ports-range", "30000:60000" ]
|
||||||
container_name: watchtower
|
|
||||||
volumes:
|
|
||||||
- /var/run/docker.sock:/var/run/docker.sock
|
|
||||||
command: snowflake-proxy
|
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ services:
|
|||||||
networks:
|
networks:
|
||||||
- web
|
- web
|
||||||
labels:
|
labels:
|
||||||
|
- "com.ghost.tel/stack-type=dev-only"
|
||||||
- "traefik.enable=true"
|
- "traefik.enable=true"
|
||||||
- "traefik.http.routers.syncthing.entrypoints=https"
|
- "traefik.http.routers.syncthing.entrypoints=https"
|
||||||
- "traefik.http.routers.syncthing.rule=Host(`syncthing.${DOMAIN}`)"
|
- "traefik.http.routers.syncthing.rule=Host(`syncthing.${DOMAIN}`)"
|
||||||
|
|||||||
@@ -3,9 +3,10 @@
|
|||||||
## Use this as a template to set up docker compose, or as guide to set up other
|
## Use this as a template to set up docker compose, or as guide to set up other
|
||||||
## orchestration services
|
## orchestration services
|
||||||
services:
|
services:
|
||||||
|
|
||||||
server:
|
server:
|
||||||
image: szurubooru/server:latest
|
image: szurubooru/server:latest
|
||||||
|
labels:
|
||||||
|
- "com.ghost.tel/stack-type=dev-only"
|
||||||
depends_on:
|
depends_on:
|
||||||
- sql
|
- sql
|
||||||
environment:
|
environment:
|
||||||
|
|||||||
0
stacks/traefik/conf.d/.gitkeep
Normal file
0
stacks/traefik/conf.d/.gitkeep
Normal file
@@ -1,61 +0,0 @@
|
|||||||
# Core middlewares for traefik
|
|
||||||
# External service routers should be added as separate files or via docker labels
|
|
||||||
|
|
||||||
http:
|
|
||||||
routers:
|
|
||||||
# Redirect HTTP to HTTPS
|
|
||||||
https-redirect:
|
|
||||||
entryPoints:
|
|
||||||
- http
|
|
||||||
rule: "HostRegexp(`{host:.+}`)"
|
|
||||||
service: noop@internal
|
|
||||||
middlewares:
|
|
||||||
- redirect-to-https
|
|
||||||
priority: 1
|
|
||||||
|
|
||||||
middlewares:
|
|
||||||
# HTTPS redirect
|
|
||||||
redirect-to-https:
|
|
||||||
redirectScheme:
|
|
||||||
scheme: https
|
|
||||||
|
|
||||||
# Authentik forward auth - update URL after authentik is deployed
|
|
||||||
auth:
|
|
||||||
forwardAuth:
|
|
||||||
address: http://authentik-server:9000/outpost.goauthentik.io/auth/traefik
|
|
||||||
trustForwardHeader: true
|
|
||||||
authResponseHeaders:
|
|
||||||
- X-authentik-username
|
|
||||||
- X-authentik-groups
|
|
||||||
- X-authentik-email
|
|
||||||
- X-authentik-name
|
|
||||||
- X-authentik-uid
|
|
||||||
- X-authentik-jwt
|
|
||||||
- X-authentik-meta-jwks
|
|
||||||
- X-authentik-meta-outpost
|
|
||||||
- X-authentik-meta-provider
|
|
||||||
- X-authentik-meta-app
|
|
||||||
- X-authentik-meta-version
|
|
||||||
|
|
||||||
# Security headers
|
|
||||||
securityHeaders:
|
|
||||||
headers:
|
|
||||||
customResponseHeaders:
|
|
||||||
X-Robots-Tag: "none,noarchive,nosnippet,notranslate,noimageindex"
|
|
||||||
server: ""
|
|
||||||
X-Forwarded-Proto: "https"
|
|
||||||
sslProxyHeaders:
|
|
||||||
X-Forwarded-Proto: https
|
|
||||||
referrerPolicy: "same-origin"
|
|
||||||
hostsProxyHeaders:
|
|
||||||
- "X-Forwarded-Host"
|
|
||||||
contentTypeNosniff: true
|
|
||||||
browserXssFilter: true
|
|
||||||
forceSTSHeader: true
|
|
||||||
stsIncludeSubdomains: true
|
|
||||||
stsSeconds: 63072000
|
|
||||||
stsPreload: true
|
|
||||||
|
|
||||||
# Gzip compression
|
|
||||||
gzip:
|
|
||||||
compress: {}
|
|
||||||
@@ -5,6 +5,137 @@ services:
|
|||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
security_opt:
|
security_opt:
|
||||||
- no-new-privileges:true
|
- no-new-privileges:true
|
||||||
|
labels:
|
||||||
|
- "com.ghost.tel/stack-type=prod"
|
||||||
|
- "traefik.enable=true"
|
||||||
|
- "traefik.http.routers.traefik.entrypoints=https"
|
||||||
|
- "traefik.http.routers.traefik.rule=Host(`traefik.ghost.tel`)"
|
||||||
|
- "traefik.http.routers.traefik.service=api@internal"
|
||||||
|
- "traefik.http.routers.traefik.middlewares=auth@docker"
|
||||||
|
- "traefik.http.routers.traefik.tls.certresolver=http"
|
||||||
|
- "traefik.http.routers.immich-redirect.entrypoints=http,https"
|
||||||
|
- "traefik.http.routers.immich-redirect.rule=Host(`immich.ghost.tel`)"
|
||||||
|
- "traefik.http.routers.immich-redirect.service=dummy"
|
||||||
|
- "traefik.http.routers.immich-redirect.middlewares=redirect-immich-to-photos@docker"
|
||||||
|
- "traefik.http.routers.immich-redirect.tls.certresolver=http"
|
||||||
|
- "traefik.http.routers.homeassist.entrypoints=https"
|
||||||
|
- "traefik.http.routers.homeassist.rule=Host(`home.ghost.tel`)"
|
||||||
|
- "traefik.http.routers.homeassist.service=homeassistant"
|
||||||
|
- "traefik.http.routers.homeassist.middlewares=securityHeaders@docker"
|
||||||
|
- "traefik.http.routers.homeassist.tls.certresolver=http"
|
||||||
|
- "traefik.http.routers.dynmap.entrypoints=http,https"
|
||||||
|
- "traefik.http.routers.dynmap.rule=Host(`dynmap.ghost.tel`)"
|
||||||
|
- "traefik.http.routers.dynmap.service=dynmap"
|
||||||
|
- "traefik.http.routers.dynmap.tls.certresolver=http"
|
||||||
|
- "traefik.http.routers.amp.entrypoints=http"
|
||||||
|
- "traefik.http.routers.amp.rule=Host(`amped.ghost.tel`)"
|
||||||
|
- "traefik.http.routers.amp.service=amp"
|
||||||
|
- "traefik.http.routers.amp.tls.certresolver=http"
|
||||||
|
- "traefik.http.routers.picam.entrypoints=http,https"
|
||||||
|
- "traefik.http.routers.picam.rule=Host(`printview.ghost.tel`)"
|
||||||
|
- "traefik.http.routers.picam.service=picam"
|
||||||
|
- "traefik.http.routers.picam.tls.certresolver=http"
|
||||||
|
- "traefik.http.routers.library.entrypoints=http,https"
|
||||||
|
- "traefik.http.routers.library.rule=Host(`library.ghost.tel`)"
|
||||||
|
- "traefik.http.routers.library.service=library"
|
||||||
|
- "traefik.http.routers.library.middlewares=securityHeaders@docker"
|
||||||
|
- "traefik.http.routers.library.tls.certresolver=http"
|
||||||
|
- "traefik.http.routers.meshmon.entrypoints=http,https"
|
||||||
|
- "traefik.http.routers.meshmon.rule=Host(`meshmon.ghost.tel`)"
|
||||||
|
- "traefik.http.routers.meshmon.service=meshmon"
|
||||||
|
- "traefik.http.routers.meshmon.middlewares=securityHeaders@docker"
|
||||||
|
- "traefik.http.routers.meshmon.tls.certresolver=http"
|
||||||
|
- "traefik.http.routers.skeyta.entrypoints=http,https"
|
||||||
|
- "traefik.http.routers.skeyta.rule=Host(`skeyta.ghost.tel`)"
|
||||||
|
- "traefik.http.routers.skeyta.service=skeyta"
|
||||||
|
- "traefik.http.routers.skeyta.middlewares=securityHeaders@docker"
|
||||||
|
- "traefik.http.routers.skeyta.tls.certresolver=http"
|
||||||
|
- "traefik.http.routers.radio.entrypoints=http,https"
|
||||||
|
- "traefik.http.routers.radio.rule=Host(`radio.uplink.tel`)"
|
||||||
|
- "traefik.http.routers.radio.service=radio-wunder"
|
||||||
|
- "traefik.http.routers.radio.middlewares=securityHeaders@docker"
|
||||||
|
- "traefik.http.routers.radio.tls.certresolver=http"
|
||||||
|
- "traefik.http.routers.sdr.entrypoints=http,https"
|
||||||
|
- "traefik.http.routers.sdr.rule=Host(`sdr.uplink.tel`)"
|
||||||
|
- "traefik.http.routers.sdr.service=sdr"
|
||||||
|
- "traefik.http.routers.sdr.middlewares=redirect-to-https"
|
||||||
|
- "traefik.http.routers.sdr.tls.certresolver=http"
|
||||||
|
- "traefik.http.routers.spider.entrypoints=http,https"
|
||||||
|
- "traefik.http.routers.spider.rule=Host(`spider.ghost.tel`)"
|
||||||
|
- "traefik.http.routers.spider.service=spider"
|
||||||
|
- "traefik.http.routers.spider.middlewares=securityHeaders@docker"
|
||||||
|
- "traefik.http.routers.spider.tls.certresolver=http"
|
||||||
|
- "traefik.http.routers.tlc.entrypoints=http,https"
|
||||||
|
- "traefik.http.routers.tlc.rule=Host(`tlc.ghost.tel`) || Host(`thislittlecorner.net`)"
|
||||||
|
- "traefik.http.routers.tlc.service=tlc"
|
||||||
|
- "traefik.http.routers.tlc.middlewares=securityHeaders@docker"
|
||||||
|
- "traefik.http.routers.tlc.tls.certresolver=http"
|
||||||
|
- "traefik.http.routers.photos.entrypoints=http,https"
|
||||||
|
- "traefik.http.routers.photos.rule=Host(`photos.ghost.tel`)"
|
||||||
|
- "traefik.http.routers.photos.service=wille"
|
||||||
|
- "traefik.http.routers.photos.middlewares=securityHeaders@docker"
|
||||||
|
- "traefik.http.routers.photos.tls.certresolver=http"
|
||||||
|
- "traefik.http.routers.invidious-uplink.entrypoints=https"
|
||||||
|
- "traefik.http.routers.invidious-uplink.rule=Host(`invidious.uplink.tel`)"
|
||||||
|
- "traefik.http.routers.invidious-uplink.service=docker-public"
|
||||||
|
- "traefik.http.routers.invidious-uplink.tls.certresolver=http"
|
||||||
|
- "traefik.http.routers.service-map.entrypoints=https"
|
||||||
|
- "traefik.http.routers.service-map.rule=Host(`map.ghost.tel`)"
|
||||||
|
- "traefik.http.routers.service-map.service=service-map"
|
||||||
|
- "traefik.http.routers.service-map.middlewares=dashboard-auth@docker"
|
||||||
|
- "traefik.http.routers.service-map.tls.certresolver=http"
|
||||||
|
- "traefik.http.services.dummy.loadbalancer.server.url=http://127.0.0.1"
|
||||||
|
- "traefik.http.services.homeassistant.loadbalancer.server.url=http://homeassistant.localdomain:8123"
|
||||||
|
- "traefik.http.services.homeassistant.loadbalancer.passHostHeader=true"
|
||||||
|
- "traefik.http.services.dynmap.loadbalancer.server.url=http://ramiel:8123/"
|
||||||
|
- "traefik.http.services.amp.loadbalancer.server.url=http://192.168.1.205:8080"
|
||||||
|
- "traefik.http.services.amp.loadbalancer.passHostHeader=true"
|
||||||
|
- "traefik.http.services.picam.loadbalancer.server.url=http://192.168.1.80:8080"
|
||||||
|
- "traefik.http.services.picam.loadbalancer.passHostHeader=true"
|
||||||
|
- "traefik.http.services.library.loadbalancer.server.url=http://docker-dev:8033/"
|
||||||
|
- "traefik.http.services.library.loadbalancer.passHostHeader=true"
|
||||||
|
- "traefik.http.services.meshmon.loadbalancer.server.url=http://ubuntu-dev:8383/"
|
||||||
|
- "traefik.http.services.meshmon.loadbalancer.passHostHeader=true"
|
||||||
|
- "traefik.http.services.skeyta.loadbalancer.server.url=http://ramiel.localdomain:8"
|
||||||
|
- "traefik.http.services.skeyta.loadbalancer.passHostHeader=true"
|
||||||
|
- "traefik.http.services.radio-wunder.loadbalancer.server.url=http://wunder.localdomain:3000"
|
||||||
|
- "traefik.http.services.sdr.loadbalancer.server.url=http://wunder.localdomain:8073"
|
||||||
|
- "traefik.http.services.sdr.loadbalancer.passHostHeader=true"
|
||||||
|
- "traefik.http.services.radio-wunder.loadbalancer.passHostHeader=true"
|
||||||
|
- "traefik.http.services.spider.loadbalancer.server.url=http://melchior.localdomain:30870"
|
||||||
|
- "traefik.http.services.spider.loadbalancer.passHostHeader=true"
|
||||||
|
- "traefik.http.services.tlc.loadbalancer.passHostHeader=true"
|
||||||
|
- "traefik.http.services.tlc.loadbalancer.server.url=http://ubuntu-dev.localdomain:8088"
|
||||||
|
- "traefik.http.services.wille.loadbalancer.server.url=http://wille.localdomain:2283"
|
||||||
|
- "traefik.http.services.wille.loadbalancer.passHostHeader=true"
|
||||||
|
- "traefik.http.services.service-map.loadbalancer.server.url=http://docker-dev:3333/"
|
||||||
|
- "traefik.http.services.service-map.loadbalancer.passHostHeader=true"
|
||||||
|
- "traefik.http.services.docker-public.loadbalancer.server.url=https://192.168.5.46:443"
|
||||||
|
- "traefik.http.services.docker-public.loadbalancer.passHostHeader=true"
|
||||||
|
- "traefik.http.services.docker-public.loadbalancer.serversTransport=insecure-transport"
|
||||||
|
- "traefik.http.serversTransports.insecure-transport.insecureSkipVerify=true"
|
||||||
|
- "traefik.http.middlewares.redirect-immich-to-photos.redirectregex.regex=^https?://immich\\.ghost\\.tel(/.*)?$"
|
||||||
|
- "traefik.http.middlewares.redirect-immich-to-photos.redirectregex.replacement=https://photos.ghost.tel$1"
|
||||||
|
- "traefik.http.middlewares.redirect-immich-to-photos.redirectregex.permanent=true"
|
||||||
|
- "traefik.http.middlewares.dashboard-auth.basicauth.usersfile=/basicAuth"
|
||||||
|
- "traefik.http.middlewares.redirect-to-https.redirectscheme.scheme=https"
|
||||||
|
- "traefik.http.middlewares.auth.forwardauth.address=http://authentik-server:9000/outpost.goauthentik.io/auth/traefik"
|
||||||
|
- "traefik.http.middlewares.auth.forwardauth.trustForwardHeader=true"
|
||||||
|
- "traefik.http.middlewares.auth.forwardauth.authResponseHeaders=X-authentik-username,X-authentik-groups,X-authentik-email,X-authentik-name,X-authentik-uid,X-authentik-jwt,X-authentik-meta-jwks,X-authentik-meta-outpost,X-authentik-meta-provider,X-authentik-meta-app,X-authentik-meta-version"
|
||||||
|
- "traefik.http.middlewares.securityHeaders.headers.customResponseHeaders.X-Robots-Tag=none,noarchive,nosnippet,notranslate,noimageindex"
|
||||||
|
- "traefik.http.middlewares.securityHeaders.headers.customResponseHeaders.server="
|
||||||
|
- "traefik.http.middlewares.securityHeaders.headers.customResponseHeaders.X-Forwarded-Proto=https"
|
||||||
|
- "traefik.http.middlewares.securityHeaders.headers.sslProxyHeaders.X-Forwarded-Proto=https"
|
||||||
|
- "traefik.http.middlewares.securityHeaders.headers.referrerPolicy=same-origin"
|
||||||
|
- "traefik.http.middlewares.securityHeaders.headers.hostsProxyHeaders=X-Forwarded-Host"
|
||||||
|
- "traefik.http.middlewares.securityHeaders.headers.contentTypeNosniff=true"
|
||||||
|
- "traefik.http.middlewares.securityHeaders.headers.browserXssFilter=true"
|
||||||
|
- "traefik.http.middlewares.securityHeaders.headers.forceSTSHeader=true"
|
||||||
|
- "traefik.http.middlewares.securityHeaders.headers.stsIncludeSubdomains=true"
|
||||||
|
- "traefik.http.middlewares.securityHeaders.headers.stsSeconds=63072000"
|
||||||
|
- "traefik.http.middlewares.securityHeaders.headers.stsPreload=true"
|
||||||
|
- "traefik.http.middlewares.invid-companion-prefix.addprefix.prefix=/companion"
|
||||||
|
- "traefik.http.middlewares.gzip.compress=true"
|
||||||
networks:
|
networks:
|
||||||
- web
|
- web
|
||||||
ports:
|
ports:
|
||||||
@@ -17,7 +148,7 @@ services:
|
|||||||
- /var/run/docker.sock:/var/run/docker.sock:ro
|
- /var/run/docker.sock:/var/run/docker.sock:ro
|
||||||
- ./traefik.yml:/traefik.yml:ro
|
- ./traefik.yml:/traefik.yml:ro
|
||||||
- ./acme.json:/acme.json
|
- ./acme.json:/acme.json
|
||||||
- ./conf.d/:/conf.d/
|
- ./basicAuth:/basicAuth:ro
|
||||||
- /var/log:/var/log
|
- /var/log:/var/log
|
||||||
|
|
||||||
networks:
|
networks:
|
||||||
|
|||||||
@@ -8,14 +8,20 @@ api:
|
|||||||
entryPoints:
|
entryPoints:
|
||||||
http:
|
http:
|
||||||
address: ":80"
|
address: ":80"
|
||||||
|
proxyProtocol:
|
||||||
|
insecure: true
|
||||||
|
http:
|
||||||
|
redirections:
|
||||||
|
entryPoint:
|
||||||
|
to: https
|
||||||
|
scheme: https
|
||||||
https:
|
https:
|
||||||
address: ":443"
|
address: ":443"
|
||||||
|
proxyProtocol:
|
||||||
|
insecure: true
|
||||||
|
|
||||||
providers:
|
providers:
|
||||||
providersThrottleDuration: 2s
|
providersThrottleDuration: 2s
|
||||||
file:
|
|
||||||
directory: "/conf.d"
|
|
||||||
watch: true
|
|
||||||
docker:
|
docker:
|
||||||
watch: true
|
watch: true
|
||||||
endpoint: "unix:///var/run/docker.sock"
|
endpoint: "unix:///var/run/docker.sock"
|
||||||
@@ -38,3 +44,22 @@ log:
|
|||||||
accessLog:
|
accessLog:
|
||||||
filePath: /var/log/traefik_access.log
|
filePath: /var/log/traefik_access.log
|
||||||
format: json
|
format: json
|
||||||
|
fields:
|
||||||
|
defaultMode: keep
|
||||||
|
names:
|
||||||
|
clientUsername: drop
|
||||||
|
headers:
|
||||||
|
defaultMode: keep
|
||||||
|
names:
|
||||||
|
User-Agent: keep
|
||||||
|
Authorization: drop
|
||||||
|
Content-Type: keep
|
||||||
|
Referer: keep
|
||||||
|
|
||||||
|
metrics:
|
||||||
|
prometheus:
|
||||||
|
buckets:
|
||||||
|
- 0.1
|
||||||
|
- 0.3
|
||||||
|
- 1.2
|
||||||
|
- 5.0
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ services:
|
|||||||
volumes:
|
volumes:
|
||||||
- ./images:/var/www/wallabag/web/assets/images
|
- ./images:/var/www/wallabag/web/assets/images
|
||||||
labels:
|
labels:
|
||||||
|
- "com.ghost.tel/stack-type=prod"
|
||||||
- "traefik.enable=true"
|
- "traefik.enable=true"
|
||||||
- "traefik.http.routers.wallabag.entrypoints=https"
|
- "traefik.http.routers.wallabag.entrypoints=https"
|
||||||
- "traefik.http.routers.wallabag.rule=Host(`wallabag.${DOMAIN}`)"
|
- "traefik.http.routers.wallabag.rule=Host(`wallabag.${DOMAIN}`)"
|
||||||
|
|||||||
@@ -3,6 +3,8 @@ services:
|
|||||||
image: containrrr/watchtower:latest
|
image: containrrr/watchtower:latest
|
||||||
container_name: watchtower
|
container_name: watchtower
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
|
labels:
|
||||||
|
- "com.ghost.tel/stack-type=prod"
|
||||||
environment:
|
environment:
|
||||||
- TZ=America/New_York
|
- TZ=America/New_York
|
||||||
- DOCKER_API_VERSION=1.44
|
- DOCKER_API_VERSION=1.44
|
||||||
|
|||||||
1
stacks/wikijs-public/.env.template
Normal file
1
stacks/wikijs-public/.env.template
Normal file
@@ -0,0 +1 @@
|
|||||||
|
WIKIJS_DB_PASSWORD=changeme
|
||||||
45
stacks/wikijs-public/docker-compose.yml
Normal file
45
stacks/wikijs-public/docker-compose.yml
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
services:
|
||||||
|
db:
|
||||||
|
image: postgres:11-alpine
|
||||||
|
container_name: wikijs-db
|
||||||
|
restart: unless-stopped
|
||||||
|
labels:
|
||||||
|
- "com.ghost.tel/stack-type=public"
|
||||||
|
environment:
|
||||||
|
POSTGRES_DB: wiki
|
||||||
|
POSTGRES_USER: wikijs
|
||||||
|
POSTGRES_PASSWORD: ${WIKIJS_DB_PASSWORD}
|
||||||
|
volumes:
|
||||||
|
- ./db-data:/var/lib/postgresql/data
|
||||||
|
logging:
|
||||||
|
driver: "none"
|
||||||
|
|
||||||
|
wiki:
|
||||||
|
image: requarks/wiki:2
|
||||||
|
container_name: wikijs
|
||||||
|
restart: unless-stopped
|
||||||
|
labels:
|
||||||
|
- "com.ghost.tel/stack-type=public"
|
||||||
|
- "traefik.enable=true"
|
||||||
|
- "traefik.http.routers.wikijs.entrypoints=https"
|
||||||
|
- "traefik.http.routers.wikijs.rule=Host(`wiki.sequela.tel`)"
|
||||||
|
- "traefik.http.routers.wikijs.tls.certresolver=http"
|
||||||
|
- "traefik.http.services.wikijs.loadbalancer.server.port=3000"
|
||||||
|
environment:
|
||||||
|
DB_TYPE: postgres
|
||||||
|
DB_HOST: db
|
||||||
|
DB_PORT: 5432
|
||||||
|
DB_USER: wikijs
|
||||||
|
DB_PASS: ${WIKIJS_DB_PASSWORD}
|
||||||
|
DB_NAME: wiki
|
||||||
|
expose:
|
||||||
|
- "3000"
|
||||||
|
depends_on:
|
||||||
|
- db
|
||||||
|
networks:
|
||||||
|
- web
|
||||||
|
- default
|
||||||
|
|
||||||
|
networks:
|
||||||
|
web:
|
||||||
|
external: true
|
||||||
@@ -14,6 +14,7 @@ services:
|
|||||||
networks:
|
networks:
|
||||||
- web
|
- web
|
||||||
labels:
|
labels:
|
||||||
|
- "com.ghost.tel/stack-type=prod"
|
||||||
- "traefik.enable=true"
|
- "traefik.enable=true"
|
||||||
- "traefik.http.routers.xbackbone.entrypoints=https"
|
- "traefik.http.routers.xbackbone.entrypoints=https"
|
||||||
- "traefik.http.routers.xbackbone.rule=Host(`xb.${DOMAIN}`)"
|
- "traefik.http.routers.xbackbone.rule=Host(`xb.${DOMAIN}`)"
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ services:
|
|||||||
container_name: zerotier-ui
|
container_name: zerotier-ui
|
||||||
restart: always
|
restart: always
|
||||||
expose:
|
expose:
|
||||||
- 3180
|
- 3000
|
||||||
volumes:
|
volumes:
|
||||||
- ./ztncui:/opt/key-networks/ztncui/etc
|
- ./ztncui:/opt/key-networks/ztncui/etc
|
||||||
- ./zt1:/var/lib/zerotier-one
|
- ./zt1:/var/lib/zerotier-one
|
||||||
@@ -13,11 +13,13 @@ services:
|
|||||||
networks:
|
networks:
|
||||||
- web
|
- web
|
||||||
labels:
|
labels:
|
||||||
|
- "com.ghost.tel/stack-type=prod"
|
||||||
- "traefik.enable=true"
|
- "traefik.enable=true"
|
||||||
- "traefik.http.routers.zerotier.entrypoints=https"
|
- "traefik.http.routers.zerotier.entrypoints=https"
|
||||||
- "traefik.http.routers.zerotier.rule=Host(`zerotierui.${DOMAIN}`)"
|
- "traefik.http.routers.zerotier.rule=Host(`zerotierui.${DOMAIN}`)"
|
||||||
- "traefik.http.routers.zerotier.tls.certresolver=http"
|
- "traefik.http.routers.zerotier.tls.certresolver=http"
|
||||||
- "traefik.http.routers.zerotier.middlewares=dashboard-auth@file"
|
- "traefik.http.routers.zerotier.middlewares=dashboard-auth@docker"
|
||||||
|
- "traefik.http.services.zerotier.loadbalancer.server.port=3000"
|
||||||
|
|
||||||
networks:
|
networks:
|
||||||
web:
|
web:
|
||||||
|
|||||||
Reference in New Issue
Block a user