Compare commits
76 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
0bad0a817e
|
|||
| 525fed3b92 | |||
|
fe5e5c5e35
|
|||
|
72aa022048
|
|||
|
f18d4d9be4
|
|||
|
45ce789f58
|
|||
|
d7c05fd058
|
|||
| c13056fba1 | |||
|
5fe8af82d5
|
|||
| 6d97246997 | |||
| 6970279311 | |||
|
02f4e0ab42
|
|||
|
4a25622552
|
|||
|
0138fbd276
|
|||
|
94b5f39207
|
|||
| 403e88d548 | |||
| d03a4844fb | |||
| 48ff08529e | |||
|
81592b6142
|
|||
| 9480576966 | |||
| 9b43a9bef4 | |||
| 2b03335af5 | |||
| ea738ec14c | |||
|
e4e9d96a0b
|
|||
| 89576032b9 | |||
| a9edfc0a25 | |||
| acb8009307 | |||
| 21f4e46028 | |||
| 0234524635 | |||
| 26f5fb2fb9 | |||
| 122e6f6986 | |||
| ce0bc4613a | |||
| 8f4f460ff3 | |||
| c048efd569 | |||
| 1f1e13ff39 | |||
| c80a6c5351 | |||
| 4fe3d660f1 | |||
| 9675eac2bf | |||
| dc7fe64fbc | |||
| 502810a12e | |||
| c047cc291d | |||
| f2b951673c | |||
| 6b7c0df586 | |||
| fb2f420520 | |||
| 60c7d4ff17 | |||
| d20ec696a3 | |||
| c030b4cffa | |||
| e0f7ab6561 | |||
| f0682319a7 | |||
| dbd3f36f76 | |||
| 4471da827c | |||
| 163ea867ce | |||
| dc75dbaf7c | |||
| db0f0f7bb6 | |||
| 5e4c60bb30 | |||
| 17cae71952 | |||
| f4c695f95e | |||
| 6bdb16ad21 | |||
| 6eb62f41cc | |||
| 586f0e3f7d | |||
| 0e46193f53 | |||
| aed28ed15c | |||
| f3b73bae11 | |||
| be049cfa0d | |||
| bfb21adff7 | |||
| 1c75382a6e | |||
| 9c5e037567 | |||
| 4f9e7ea990 | |||
| 9f784d2c31 | |||
| a07e27bff6 | |||
| c31369f2b7 | |||
| 3bfcd6edf4 | |||
| 6843befac3 | |||
| 0dfb09590d | |||
| 625eb9561b | |||
| b367b64879 |
+20
-7
@@ -2,12 +2,8 @@
|
||||
sync.ffs_lock
|
||||
.sync.ffs_db
|
||||
|
||||
# Environment
|
||||
.env
|
||||
.env.anna
|
||||
.env.forust
|
||||
.env.*
|
||||
!.env.*example
|
||||
# Copyparty
|
||||
*.hist/
|
||||
|
||||
# Volumes and data directories
|
||||
gitea/gitea-db/
|
||||
@@ -21,6 +17,10 @@ metube/MeTube_downloads
|
||||
uptime-kuma/data/
|
||||
termix/termix-data/*
|
||||
cfddns/config.json
|
||||
checkmk/checkmk/*
|
||||
downtify/Downtify_downloads
|
||||
headscale/config/*
|
||||
headscale/data/*
|
||||
|
||||
# Steaming services files
|
||||
streaming/jellyfin/*
|
||||
@@ -32,11 +32,16 @@ streaming/qbittorrent/*
|
||||
streaming/prowlarr/*
|
||||
|
||||
# Homepage
|
||||
homepage/files/assets/images/team/*
|
||||
homepages/forust_files/assets/images/team/*
|
||||
homepages/forust_files/.well-known/*
|
||||
|
||||
# Traefik files
|
||||
traefik/letsencrypt/acme.json
|
||||
traefik/dynamic/fileservers.yml
|
||||
traefik/logs/*
|
||||
|
||||
# SSL Certificates
|
||||
adguardhome/certs/*
|
||||
traefik/certs/*
|
||||
|
||||
# Monitoring
|
||||
@@ -79,3 +84,11 @@ replacements.txt
|
||||
|
||||
# Temp files
|
||||
edu_master/temp/
|
||||
temp/*
|
||||
|
||||
# Environment
|
||||
.env
|
||||
.env.anna
|
||||
.env.forust
|
||||
.env.*
|
||||
!*example
|
||||
+18
-18
@@ -3,48 +3,48 @@ services:
|
||||
image: adguard/adguardhome:latest
|
||||
container_name: adguardhome
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
- TZ=${TZ}
|
||||
ports:
|
||||
- "53:53/tcp"
|
||||
- "53:53/udp"
|
||||
- "853:853/tcp" # DNS over TLS
|
||||
# - "67:67/udp" # DHCP
|
||||
# - "68:68/tcp" # DHCP
|
||||
- "3000:3000/tcp"
|
||||
# - "3000:3000/tcp"
|
||||
volumes:
|
||||
- ./data/work:/opt/adguardhome/work
|
||||
- ./data/conf:/opt/adguardhome/conf
|
||||
networks:
|
||||
- traefik-proxy
|
||||
- ./certs:/certs:ro
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.docker.network=traefik-proxy"
|
||||
|
||||
- "traefik.docker.network=proxy"
|
||||
- "traefik.http.services.adguard.loadbalancer.server.port=3000"
|
||||
|
||||
# Prod Router
|
||||
- "traefik.http.routers.adguard.rule=Host(`adguard.forust.xyz`)"
|
||||
- "traefik.http.routers.adguard.rule=Host(`dns.forust.xyz`) || Host(`adguard.forust.xyz`)"
|
||||
- "traefik.http.routers.adguard.entrypoints=websecure"
|
||||
- "traefik.http.routers.adguard.middlewares=security-headers@file"
|
||||
- "traefik.http.routers.adguard.service=adguard"
|
||||
- "traefik.http.routers.adguard.tls=true"
|
||||
- "traefik.http.services.adguard.loadbalancer.server.port=3000"
|
||||
|
||||
# Local Router
|
||||
- "traefik.http.routers.adguard-local.rule=Host(`adguard.workstation.internal`) || Host(`adguard.internal`)"
|
||||
- "traefik.http.routers.adguard-local.rule=Host(`adguard.workstation.internal`) || Host(`dns.workstation.internal`)"
|
||||
- "traefik.http.routers.adguard-local.entrypoints=websecure"
|
||||
- "traefik.http.routers.adguard-local.middlewares=security-headers@file"
|
||||
- "traefik.http.routers.adguard-local.service=adguard"
|
||||
- "traefik.http.routers.adguard-local.tls=true"
|
||||
|
||||
# Dev Router
|
||||
- "traefik.http.routers.adguard-dev.rule=Host(`adguard.gigaforust.internal`)"
|
||||
- "traefik.http.routers.adguard-dev.rule=Host(`adguard.gigaforust.internal`) Host(`dns.gigaforust.internal`)"
|
||||
- "traefik.http.routers.adguard-dev.entrypoints=websecure"
|
||||
- "traefik.http.routers.adguard-dev.middlewares=security-headers@file"
|
||||
- "traefik.http.routers.adguard-dev.service=adguard"
|
||||
- "traefik.http.routers.adguard-dev.tls=true"
|
||||
|
||||
# DoH Router
|
||||
- "traefik.http.routers.dns.rule=(Host(`dns.forust.xyz`) && PathPrefix(`/dns-query`))"
|
||||
- "traefik.http.routers.dns.entrypoints=websecure"
|
||||
- "traefik.http.routers.dns.tls.certresolver=letsencrypt"
|
||||
|
||||
# Glance Metadata
|
||||
- glance.name=adguard
|
||||
- glance.url=https://adguard.forust.xyz/
|
||||
- glance.description=AdGuard Home is a network-wide software for blocking ads.
|
||||
networks:
|
||||
- proxy
|
||||
networks:
|
||||
traefik-proxy:
|
||||
proxy:
|
||||
external: true
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
# ===================================
|
||||
# Authentification app (authentik)
|
||||
|
||||
# PostgresQL conf
|
||||
PG_PASS=change_this_cuz_its_ur_db_pass
|
||||
PG_USER=authentik # it's okay
|
||||
|
||||
# Image Settings
|
||||
AUTHENTIK_IMAGE=ghcr.io/goauthentik/server
|
||||
AUTHENTIK_TAG=2025.10.2
|
||||
|
||||
# Networking
|
||||
PORT_HTTP=9000
|
||||
PORT_HTTPS=9443 # btw likely already used by portainer
|
||||
|
||||
AUTHENTIK_SECRET_KEY=super_secret_super_scary_authenik_key
|
||||
|
||||
AUTHENTIK_BOOTSTRAP_PASSWORD=pls_change_this
|
||||
|
||||
AUTHENTIK_ERROR_REPORTING__ENABLED=true # Or false to turn off
|
||||
@@ -0,0 +1,101 @@
|
||||
services:
|
||||
postgresql:
|
||||
image: docker.io/library/postgres:15-alpine
|
||||
restart: unless-stopped
|
||||
env_file:
|
||||
- .env
|
||||
environment:
|
||||
POSTGRES_DB: ${PG_DB:-authentik}
|
||||
POSTGRES_PASSWORD: ${PG_PASS:?database password required}
|
||||
POSTGRES_USER: ${PG_USER:-authentik}
|
||||
healthcheck:
|
||||
interval: 30s
|
||||
retries: 5
|
||||
start_period: 20s
|
||||
test:
|
||||
- CMD-SHELL
|
||||
- pg_isready -d $${POSTGRES_DB} -U $${POSTGRES_USER}
|
||||
timeout: 5s
|
||||
volumes:
|
||||
- database:/var/lib/postgresql/data
|
||||
networks:
|
||||
- authentik
|
||||
|
||||
server:
|
||||
image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2025.10.2}
|
||||
command: server
|
||||
container_name: authentik-server
|
||||
restart: unless-stopped
|
||||
# ports:
|
||||
# - ${PORT_HTTP:-9000}:9000
|
||||
# - ${PORT_HTTPS:-9443}:9443
|
||||
env_file:
|
||||
- .env
|
||||
environment:
|
||||
AUTHENTIK_POSTGRESQL__HOST: postgresql
|
||||
AUTHENTIK_POSTGRESQL__NAME: ${PG_DB:-authentik}
|
||||
AUTHENTIK_POSTGRESQL__PASSWORD: ${PG_PASS}
|
||||
AUTHENTIK_POSTGRESQL__USER: ${PG_USER:-authentik}
|
||||
AUTHENTIK_SECRET_KEY: ${AUTHENTIK_SECRET_KEY:?secret key required}
|
||||
volumes:
|
||||
- ./media:/media
|
||||
- ./custom-templates:/templates
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.docker.network=proxy"
|
||||
- "traefik.http.services.authentik-server.loadbalancer.server.port=9000"
|
||||
|
||||
# Prod Router
|
||||
- "traefik.http.routers.authentik-server.rule=Host(`auth.forust.xyz`)"
|
||||
- "traefik.http.routers.authentik-server.entrypoints=websecure"
|
||||
- "traefik.http.routers.authentik-server.middlewares=security-headers@file"
|
||||
- "traefik.http.routers.authentik-server.service=authentik-server"
|
||||
- "traefik.http.routers.authentik-server.tls=true"
|
||||
# Local Router
|
||||
- "traefik.http.routers.authentik-server-local.rule=Host(`auth.workstation.internal`) || Host(`auth-dashboard.internal`)"
|
||||
- "traefik.http.routers.authentik-server-local.entrypoints=websecure"
|
||||
- "traefik.http.routers.authentik-server-local.middlewares=security-headers@file"
|
||||
- "traefik.http.routers.authentik-server-local.service=authentik-server"
|
||||
- "traefik.http.routers.authentik-server-local.tls=true"
|
||||
# Dev Router
|
||||
- "traefik.http.routers.authentik-server-dev.rule=Host(`auth.gigaforust.internal`)"
|
||||
- "traefik.http.routers.authentik-server-dev.entrypoints=websecure"
|
||||
- "traefik.http.routers.authentik-server-dev.middlewares=security-headers@file"
|
||||
- "traefik.http.routers.authentik-server-dev.service=authentik-server"
|
||||
- "traefik.http.routers.authentik-server-dev.tls=true"
|
||||
networks:
|
||||
- proxy
|
||||
- authentik
|
||||
depends_on:
|
||||
postgresql:
|
||||
condition: service_healthy
|
||||
worker:
|
||||
image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2025.10.2}
|
||||
restart: unless-stopped
|
||||
user: root
|
||||
command: worker
|
||||
env_file:
|
||||
- .env
|
||||
environment:
|
||||
AUTHENTIK_POSTGRESQL__HOST: postgresql
|
||||
AUTHENTIK_POSTGRESQL__NAME: ${PG_DB:-authentik}
|
||||
AUTHENTIK_POSTGRESQL__PASSWORD: ${PG_PASS}
|
||||
AUTHENTIK_POSTGRESQL__USER: ${PG_USER:-authentik}
|
||||
AUTHENTIK_SECRET_KEY: ${AUTHENTIK_SECRET_KEY:?secret key required}
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
- ./media:/media
|
||||
- ./certs:/certs
|
||||
- ./custom-templates:/templates
|
||||
networks:
|
||||
- authentik
|
||||
depends_on:
|
||||
postgresql:
|
||||
condition: service_healthy
|
||||
volumes:
|
||||
database:
|
||||
driver: local
|
||||
networks:
|
||||
authentik:
|
||||
proxy:
|
||||
external: true
|
||||
+1
-1
@@ -2,6 +2,7 @@ services:
|
||||
cloudflare-ddns:
|
||||
image: timothyjmiller/cloudflare-ddns:latest
|
||||
container_name: cloudflare-ddns
|
||||
restart: unless-stopped
|
||||
security_opt:
|
||||
- no-new-privileges:true
|
||||
network_mode: 'host'
|
||||
@@ -10,4 +11,3 @@ services:
|
||||
- PGID=1000
|
||||
volumes:
|
||||
- ./config.json:/config.json
|
||||
restart: unless-stopped
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
CMK_PASSWORD=password
|
||||
TZ=Europe/Berlin
|
||||
@@ -0,0 +1,42 @@
|
||||
services:
|
||||
checkmk:
|
||||
image: "checkmk/check-mk-raw:2.4.0-latest"
|
||||
container_name: "checkmk"
|
||||
restart: unless-stopped
|
||||
# ports:
|
||||
# - 5000:5000
|
||||
# - 6776:8000
|
||||
volumes:
|
||||
- sites:/omd/sites
|
||||
tmpfs:
|
||||
- /opt/omd/sites/cmk/tmp:uid=1000,gid=1000
|
||||
environment:
|
||||
- CMK_PASSWORD=${CMK_PASSWORD:-password}
|
||||
- CMK_SITE_ID=cmk
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.docker.network=proxy"
|
||||
- "traefik.http.services.checkmk.loadbalancer.server.port=5000"
|
||||
|
||||
# Prod Router
|
||||
- "traefik.http.routers.checkmk.rule=Host(`cmk.forust.xyz`)"
|
||||
- "traefik.http.routers.checkmk.entrypoints=websecure"
|
||||
- "traefik.http.routers.checkmk.middlewares=security-headers@file"
|
||||
- "traefik.http.routers.checkmk.tls=true"
|
||||
# Local Router
|
||||
- "traefik.http.routers.checkmk-local.rule=Host(`cmk.workstation.internal`)"
|
||||
- "traefik.http.routers.checkmk-local.entrypoints=websecure"
|
||||
- "traefik.http.routers.checkmk-local.middlewares=security-headers@file"
|
||||
- "traefik.http.routers.checkmk-local.tls=true"
|
||||
# Dev Router
|
||||
- "traefik.http.routers.checkmk-dev.rule=Host(`cmk.gigaforust.internal`)"
|
||||
- "traefik.http.routers.checkmk-dev.middlewares=security-headers@file"
|
||||
- "traefik.http.routers.checkmk-dev.entrypoints=websecure"
|
||||
- "traefik.http.routers.checkmk-dev.tls=true"
|
||||
networks:
|
||||
- proxy
|
||||
networks:
|
||||
proxy:
|
||||
external: true
|
||||
volumes:
|
||||
sites:
|
||||
+18
-22
@@ -3,52 +3,48 @@ services:
|
||||
image: darthnorse/dockmon:latest
|
||||
container_name: dockmon
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- 8000:443
|
||||
environment:
|
||||
- TZ=Europe/Bratislava
|
||||
# ports:
|
||||
# - 8000:443
|
||||
volumes:
|
||||
- ./data:/app/data
|
||||
- data:/app/data
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
healthcheck:
|
||||
test: [ "CMD", "curl", "-k", "-f", "https://localhost:443/health" ]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
networks:
|
||||
- traefik-proxy
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.docker.network=traefik-proxy"
|
||||
|
||||
# Prod Router
|
||||
- "traefik.http.routers.dockmon.rule=Host(`dockmon.forust.xyz`)"
|
||||
- "traefik.http.routers.dockmon.entrypoints=websecure"
|
||||
- "traefik.http.routers.dockmon.middlewares=security-headers@file,dockmon-auth@file"
|
||||
- "traefik.http.routers.dockmon.service=dockmon"
|
||||
- "traefik.http.routers.dockmon.tls=true"
|
||||
- "traefik.docker.network=proxy"
|
||||
- "traefik.http.services.dockmon.loadbalancer.server.port=443"
|
||||
- "traefik.http.services.dockmon.loadbalancer.server.scheme=https"
|
||||
- "traefik.http.services.dockmon.loadbalancer.serverstransport=insecureTransport@file"
|
||||
|
||||
# Prod Router
|
||||
- "traefik.http.routers.dockmon.rule=Host(`dockmon.forust.xyz`)"
|
||||
- "traefik.http.routers.dockmon.entrypoints=websecure"
|
||||
- "traefik.http.routers.dockmon.middlewares=security-chain@file"
|
||||
- "traefik.http.routers.dockmon.service=dockmon"
|
||||
- "traefik.http.routers.dockmon.tls=true"
|
||||
# Local Router
|
||||
- "traefik.http.routers.dockmon-local.rule=Host(`dockmon.workstation.internal`) || Host(`dockmon.internal`)"
|
||||
- "traefik.http.routers.dockmon-local.rule=Host(`dockmon.workstation.internal`)"
|
||||
- "traefik.http.routers.dockmon-local.entrypoints=websecure"
|
||||
- "traefik.http.routers.dockmon-local.middlewares=security-headers@file"
|
||||
- "traefik.http.routers.dockmon-local.service=dockmon"
|
||||
- "traefik.http.routers.dockmon-local.tls=true"
|
||||
|
||||
# Dev Router
|
||||
- "traefik.http.routers.dockmon-dev.rule=Host(`dockmon.gigaforust.internal`)"
|
||||
- "traefik.http.routers.dockmon-dev.entrypoints=websecure"
|
||||
- "traefik.http.routers.dockmon-dev.middlewares=security-headers@file"
|
||||
- "traefik.http.routers.dockmon-dev.service=dockmon"
|
||||
- "traefik.http.routers.dockmon-dev.middlewares=security-chain@file"
|
||||
- "traefik.http.routers.dockmon-dev.tls=true"
|
||||
|
||||
# Glance Metadata
|
||||
- glance.name=dockmon
|
||||
- glance.url=https://dockmon.forust.xyz/
|
||||
- glance.description=Dockmon is a lightweight Docker container monitoring and management tool with a user-friendly web interface.
|
||||
|
||||
networks:
|
||||
- proxy
|
||||
volumes:
|
||||
data:
|
||||
networks:
|
||||
traefik-proxy:
|
||||
proxy:
|
||||
external: true
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
services:
|
||||
downtify:
|
||||
container_name: downtify
|
||||
image: ghcr.io/henriquesebastiao/downtify:latest
|
||||
# ports:
|
||||
# - '7077:8000'
|
||||
volumes:
|
||||
- ./Downtify_downloads:/downloads
|
||||
labels:
|
||||
- traefik.enable=true
|
||||
- traefik.docker.network=proxy
|
||||
- traefik.http.services.downtify.loadbalancer.server.port=8000
|
||||
|
||||
# Prod Router
|
||||
- traefik.http.routers.downtify.rule=Host(`downtify.forust.xyz`)
|
||||
- traefik.http.routers.downtify.entrypoints=websecure
|
||||
- traefik.http.routers.downtify.middlewares=security-chain@file
|
||||
- traefik.http.routers.downtify.tls=true
|
||||
# Local Router
|
||||
- traefik.http.routers.downtify-local.rule=Host(`downtify.workstation.internal`) || Host(`downtify.internal`)
|
||||
- traefik.http.routers.downtify-local.entrypoints=websecure
|
||||
- traefik.http.routers.downtify-local.middlewares=security-headers@file
|
||||
- traefik.http.routers.downtify-local.tls=true
|
||||
# Dev Router
|
||||
- traefik.http.routers.downtify-dev.rule=Host(`downtify.gigaforust.internal`)
|
||||
- traefik.http.routers.downtify-dev.entrypoints=websecure
|
||||
- traefik.http.routers.downtify-dev.middlewares=security-chain@file
|
||||
- traefik.http.routers.downtify-dev.tls=true
|
||||
networks:
|
||||
- proxy
|
||||
networks:
|
||||
proxy:
|
||||
external: true
|
||||
@@ -12,15 +12,26 @@ logging.basicConfig(
|
||||
)
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
# Load configuration
|
||||
LOGIN = os.getenv('EDU_LOGIN')
|
||||
PASSWORD = os.getenv('EDU_PASSWORD')
|
||||
URL_LOGIN = os.getenv('EDU_URL_LOGIN', 'https://edu.edu.vn.ua/user/login')
|
||||
URL_VERIFY = os.getenv('EDU_URL_VERIFY', 'https://edu.edu.vn.ua/course/userlist')
|
||||
INTERVAL = int(os.getenv('PHPSESSID_INTERVAL', 10))
|
||||
USER_AGENT = os.getenv('USER_AGENT', 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36')
|
||||
REDIS_HOST = os.getenv('REDIS_HOST', 'redis')
|
||||
REDIS_PORT = int(os.getenv('REDIS_PORT', 6379))
|
||||
# Load configuration (adapted to .env keys)
|
||||
def _env(key, default=None):
|
||||
v = os.getenv(key, default)
|
||||
if isinstance(v, str) and len(v) >= 2 and ((v[0] == '"' and v[-1] == '"') or (v[0] == "'" and v[-1] == "'")):
|
||||
return v[1:-1]
|
||||
return v
|
||||
|
||||
LOGIN = _env('KEEPER_LOGIN')
|
||||
PASSWORD = _env('KEEPER_PASSWORD')
|
||||
|
||||
EDU_BASE = _env('EDU_URL_BASE', 'https://edu.edu.vn.ua')
|
||||
EDU_LOGIN_PATH = _env('EDU_URL_LOGIN', '/user/login')
|
||||
EDU_COURSES_PATH = _env('EDU_URL_COURSES', '/course/userlist')
|
||||
URL_LOGIN = f"{EDU_BASE.rstrip('/')}/{EDU_LOGIN_PATH.lstrip('/')}"
|
||||
URL_VERIFY = f"{EDU_BASE.rstrip('/')}/{EDU_COURSES_PATH.lstrip('/')}"
|
||||
|
||||
INTERVAL = int(_env('KEEPER_INTERVAL', 10))
|
||||
USER_AGENT = _env('USER_AGENT', 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36')
|
||||
REDIS_HOST = _env('REDIS_HOST', 'redis')
|
||||
REDIS_PORT = int(_env('REDIS_PORT', 6379))
|
||||
|
||||
SUCCESS_FILE = '/tmp/last_success'
|
||||
|
||||
|
||||
@@ -3,7 +3,8 @@ import logging
|
||||
import redis
|
||||
import json
|
||||
|
||||
from telegram import Update, InlineKeyboardButton, InlineKeyboardMarkup
|
||||
from telegram import Update, InlineKeyboardButton, InlineKeyboardMarkup, ChatMember
|
||||
from telegram.constants import ChatType
|
||||
from telegram.ext import Application, CommandHandler, CallbackQueryHandler, ContextTypes
|
||||
from playwright.async_api import async_playwright
|
||||
|
||||
@@ -14,22 +15,36 @@ logging.basicConfig(
|
||||
)
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
# Suppress HTTP request logs
|
||||
logging.getLogger('urllib3').setLevel(logging.WARNING)
|
||||
logging.getLogger('httpx').setLevel(logging.WARNING)
|
||||
logging.getLogger('telegram.ext._application').setLevel(logging.WARNING)
|
||||
|
||||
# Load environment variables
|
||||
WEBINAR_URL = os.getenv('WEBINAR_URL', 'https://edu.edu.vn.ua/webinar/useractive')
|
||||
WEBINAR_CHECK_INTERVAL = int(os.getenv('WEBINAR_CHECK_INTERVAL', 60))
|
||||
REDIS_HOST = os.getenv('REDIS_HOST', 'redis')
|
||||
REDIS_PORT = int(os.getenv('REDIS_PORT', 6379))
|
||||
PLAYWRIGHT_WS = os.getenv('PLAYWRIGHT_WS', 'ws://playwright-service:3000/ws')
|
||||
USER_AGENT = os.getenv('USER_AGENT', 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36')
|
||||
WEBINAR_TELEGRAM_TOKEN = os.getenv('WEBINAR_TELEGRAM_TOKEN')
|
||||
ADMIN_ID = int(os.getenv('WEBINAR_ADMIN_ID', '0'))
|
||||
def _env(key, default=None):
|
||||
v = os.getenv(key, default)
|
||||
if isinstance(v, str) and len(v) >= 2 and ((v[0] == '"' and v[-1] == '"') or (v[0] == "'" and v[-1] == "'")):
|
||||
return v[1:-1]
|
||||
return v
|
||||
|
||||
EDU_BASE = _env('EDU_URL_BASE', 'https://edu.edu.vn.ua')
|
||||
EDU_WEBINAR_PATH = _env('EDU_URL_WEBINAR', '/webinar/useractive')
|
||||
WEBINAR_URL = f"{EDU_BASE.rstrip('/')}/{EDU_WEBINAR_PATH.lstrip('/')}"
|
||||
|
||||
WEBINAR_CHECK_INTERVAL = int(_env('WEBINAR_CHECK_INTERVAL', 60))
|
||||
REDIS_HOST = _env('REDIS_HOST', 'redis')
|
||||
REDIS_PORT = int(_env('REDIS_PORT', 6379))
|
||||
PLAYWRIGHT_WS = _env('PLAYWRIGHT_WS', 'ws://playwright-service:3000/ws')
|
||||
USER_AGENT = _env('USER_AGENT', 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36')
|
||||
WEBINAR_TELEGRAM_TOKEN = _env('WEBINAR_TELEGRAM_TOKEN')
|
||||
ADMIN_ID = int(_env('WEBINAR_ADMIN_ID', '0'))
|
||||
|
||||
# Redis Keys
|
||||
KEY_WHITELIST = "bot:whitelist"
|
||||
KEY_WHITELIST_ENABLED = "bot:whitelist_enabled"
|
||||
KEY_SUBSCRIBERS = "bot:subscribers"
|
||||
KEY_PHPSESSID = "EDU_PHPSESSID"
|
||||
KEY_WEBINAR_HISTORY = "bot:webinar_history" # Stores last 5 webinars
|
||||
KEY_WEBINAR_HISTORY = "bot:webinar_history" # Stores last 3 webinars
|
||||
|
||||
# Initialize Redis
|
||||
try:
|
||||
@@ -48,7 +63,7 @@ TRANSLATIONS = {
|
||||
'welcome_admin': "\n\n👑 <b>Режим администратора активен</b>",
|
||||
'access_denied': "⛔ Доступ запрещен. Вас нет в белом списке.",
|
||||
'help_title': "🤖 <b>Помощь по боту</b>\n\n",
|
||||
'help_commands': "/start - Подписаться на уведомления\n/help - Показать это сообщение\n/language - Сменить язык",
|
||||
'help_commands': "/start - Подписаться на уведомления\n/stop - Отписаться от уведомлений\n/help - Показать это сообщение\n/language - Сменить язык",
|
||||
'help_admin': "\n<b>Команды администратора:</b>\n/adduser [user_id] - Добавить пользователя в белый список\n/removeuser [user_id] - Удалить пользователя из белого списка\nИли используйте панель ниже для управления настройками.",
|
||||
'admin_only': "⛔ Только для администратора!",
|
||||
'user_added': "✅ Пользователь {user_id} добавлен в белый список",
|
||||
@@ -79,13 +94,15 @@ TRANSLATIONS = {
|
||||
'flag_ru': "🇷🇺 Русский",
|
||||
'flag_uk': "🇺🇦 Українська",
|
||||
'flag_en': "🇬🇧 English",
|
||||
'history_cleared': "✅ История вебинаров очищена",
|
||||
'history_clear_failed': "❌ Ошибка при очистке истории",
|
||||
},
|
||||
'uk': {
|
||||
'welcome': "👋 Привіт, {name}!\n\nЯ бот-сповіщувач про вебінари. Я повідомлятиму вас, коли з'явиться новий вебінар.\nВи підписані на сповіщення.",
|
||||
'welcome_admin': "\n\n👑 <b>Режим адміністратора активний</b>",
|
||||
'access_denied': "⛔ Доступ заборонено. Вас немає в білому списку.",
|
||||
'help_title': "🤖 <b>Довідка по боту</b>\n\n",
|
||||
'help_commands': "/start - Підписатися на сповіщення\n/help - Показати це повідомлення\n/language - Змінити мову",
|
||||
'help_commands': "/start - Підписатися на сповіщення\n/stop - Відписатися від сповіщень\n/help - Показати це повідомлення\n/language - Змінити мову",
|
||||
'help_admin': "\n<b>Команди адміністратора:</b>\n/adduser [user_id] - Додати користувача до білого списку\n/removeuser [user_id] - Видалити користувача з білого списку\nАбо використовуйте панель нижче для керування налаштуваннями.",
|
||||
'admin_only': "⛔ Тільки для адміністратора!",
|
||||
'user_added': "✅ Користувач {user_id} доданий до білого списку",
|
||||
@@ -116,13 +133,15 @@ TRANSLATIONS = {
|
||||
'flag_ru': "🇷🇺 Русский",
|
||||
'flag_uk': "🇺🇦 Українська",
|
||||
'flag_en': "🇬🇧 English",
|
||||
'history_cleared': "✅ Історія вебінарів очищена",
|
||||
'history_clear_failed': "❌ Помилка при очищенні історії",
|
||||
},
|
||||
'en': {
|
||||
'welcome': "👋 Hello, {name}!\n\nI am the Webinar Checker Bot. I will notify you when a new webinar appears.\nYou have been subscribed to notifications.",
|
||||
'welcome_admin': "\n\n👑 <b>Admin Mode Active</b>",
|
||||
'access_denied': "⛔ Access denied. You are not on the whitelist.",
|
||||
'help_title': "🤖 <b>Bot Help</b>\n\n",
|
||||
'help_commands': "/start - Subscribe to notifications\n/help - Show this message\n/language - Change language",
|
||||
'help_commands': "/start - Subscribe to notifications\n/stop - Unsubscribe from notifications\n/help - Show this message\n/language - Change language",
|
||||
'help_admin': "\n<b>Admin Commands:</b>\n/adduser [user_id] - Add user to whitelist\n/removeuser [user_id] - Remove user from whitelist\nOr use the panel below to manage settings.",
|
||||
'admin_only': "⛔ Admin only!",
|
||||
'user_added': "✅ User {user_id} added to whitelist",
|
||||
@@ -153,6 +172,8 @@ TRANSLATIONS = {
|
||||
'flag_ru': "🇷🇺 Русский",
|
||||
'flag_uk': "🇺🇦 Українська",
|
||||
'flag_en': "🇬🇧 English",
|
||||
'history_cleared': "✅ Webinar history cleared",
|
||||
'history_clear_failed': "❌ Error clearing history",
|
||||
}
|
||||
}
|
||||
|
||||
@@ -203,6 +224,21 @@ def is_whitelisted(user_id: int) -> bool:
|
||||
|
||||
return redis_client.sismember(KEY_WHITELIST, str(user_id))
|
||||
|
||||
async def is_group_admin(update: Update, context: ContextTypes.DEFAULT_TYPE) -> bool:
|
||||
"""Check if the user is an administrator in the group."""
|
||||
user = update.effective_user
|
||||
chat = update.effective_chat
|
||||
|
||||
if chat.type in [ChatType.PRIVATE, "private"]:
|
||||
return True
|
||||
|
||||
try:
|
||||
member = await context.bot.get_chat_member(chat.id, user.id)
|
||||
return member.status in [ChatMember.OWNER, ChatMember.ADMINISTRATOR]
|
||||
except Exception as e:
|
||||
logger.error(f"Failed to check admin status: {e}")
|
||||
return False
|
||||
|
||||
def get_admin_keyboard(user_id: int):
|
||||
"""Generate admin panel keyboard."""
|
||||
whitelist_enabled = redis_client.get(KEY_WHITELIST_ENABLED) != "0"
|
||||
@@ -221,19 +257,21 @@ def get_admin_keyboard(user_id: int):
|
||||
async def start(update: Update, context: ContextTypes.DEFAULT_TYPE):
|
||||
"""Handle /start command."""
|
||||
user = update.effective_user
|
||||
logger.info(f"User {user.id} ({user.username}) started the bot.")
|
||||
chat = update.effective_chat
|
||||
logger.info(f"User {user.id} ({user.username}) started the bot in chat {chat.id} ({chat.type}).")
|
||||
|
||||
# Check whitelist - MUST be the user executing the command
|
||||
if not is_whitelisted(user.id):
|
||||
await update.message.reply_text(t(user.id, 'access_denied'))
|
||||
return
|
||||
|
||||
# Add to subscribers
|
||||
redis_client.sadd(KEY_SUBSCRIBERS, user.id)
|
||||
# Add to subscribers (Chat ID!)
|
||||
redis_client.sadd(KEY_SUBSCRIBERS, chat.id)
|
||||
|
||||
msg = t(user.id, 'welcome', name=user.first_name)
|
||||
msg = t(chat.id, 'welcome', name=user.first_name)
|
||||
|
||||
if user.id == ADMIN_ID:
|
||||
msg += t(user.id, 'welcome_admin')
|
||||
if user.id == ADMIN_ID and chat.type == "private":
|
||||
msg += t(chat.id, 'welcome_admin')
|
||||
await update.message.reply_text(msg, parse_mode='HTML', reply_markup=get_admin_keyboard(user.id))
|
||||
else:
|
||||
await update.message.reply_text(msg, parse_mode='HTML')
|
||||
@@ -241,19 +279,39 @@ async def start(update: Update, context: ContextTypes.DEFAULT_TYPE):
|
||||
async def help_command(update: Update, context: ContextTypes.DEFAULT_TYPE):
|
||||
"""Handle /help command."""
|
||||
user_id = update.effective_user.id
|
||||
msg = t(user_id, 'help_title') + t(user_id, 'help_commands')
|
||||
chat_id = update.effective_chat.id
|
||||
msg = t(chat_id, 'help_title') + t(chat_id, 'help_commands')
|
||||
|
||||
if user_id == ADMIN_ID:
|
||||
msg += t(user_id, 'help_admin')
|
||||
if user_id == ADMIN_ID and update.effective_chat.type == "private":
|
||||
msg += t(chat_id, 'help_admin')
|
||||
await update.message.reply_text(msg, parse_mode='HTML', reply_markup=get_admin_keyboard(user_id))
|
||||
else:
|
||||
await update.message.reply_text(msg, parse_mode='HTML')
|
||||
|
||||
async def stop_command(update: Update, context: ContextTypes.DEFAULT_TYPE):
|
||||
"""Handle /stop command (unsubscribe)."""
|
||||
user = update.effective_user
|
||||
chat = update.effective_chat
|
||||
|
||||
# Permission check: Whitelisted user OR Group Admin
|
||||
if not (is_whitelisted(user.id) or await is_group_admin(update, context)):
|
||||
await update.message.reply_text(t(chat.id, 'access_denied')) # Or specific "admin only" message
|
||||
return
|
||||
|
||||
redis_client.srem(KEY_SUBSCRIBERS, chat.id)
|
||||
await update.message.reply_text(t(chat.id, 'whitelist_disabled').replace(" whitelist", " notifications").replace("Білий список", "Сповіщення").replace("Белый список", "Уведомления") if chat.id else "Unsubscribed")
|
||||
|
||||
async def language_command(update: Update, context: ContextTypes.DEFAULT_TYPE):
|
||||
"""Handle /language command."""
|
||||
user_id = update.effective_user.id
|
||||
user = update.effective_user
|
||||
chat = update.effective_chat
|
||||
|
||||
# Permission check for groups
|
||||
if not (is_whitelisted(user.id) or await is_group_admin(update, context)):
|
||||
return
|
||||
|
||||
await update.message.reply_text(
|
||||
t(user_id, 'select_language'),
|
||||
t(chat.id, 'select_language'),
|
||||
parse_mode='HTML',
|
||||
reply_markup=get_language_keyboard()
|
||||
)
|
||||
@@ -303,6 +361,21 @@ async def remove_user(update: Update, context: ContextTypes.DEFAULT_TYPE):
|
||||
except ValueError:
|
||||
await update.message.reply_text(t(admin_id, 'invalid_user_id'))
|
||||
|
||||
async def clear_history(update: Update, context: ContextTypes.DEFAULT_TYPE):
|
||||
"""Clear webinar history (admin only)."""
|
||||
admin_id = update.effective_user.id
|
||||
if admin_id != ADMIN_ID:
|
||||
await update.message.reply_text(t(admin_id, 'admin_only'))
|
||||
return
|
||||
|
||||
try:
|
||||
redis_client.delete(KEY_WEBINAR_HISTORY)
|
||||
await update.message.reply_text(t(admin_id, 'history_cleared'))
|
||||
logger.info("Admin cleared webinar history")
|
||||
except Exception as e:
|
||||
logger.error(f"Failed to clear history: {e}")
|
||||
await update.message.reply_text(t(admin_id, 'history_clear_failed'))
|
||||
|
||||
# --- Admin Callbacks ---
|
||||
|
||||
async def admin_callback(update: Update, context: ContextTypes.DEFAULT_TYPE):
|
||||
@@ -363,9 +436,9 @@ async def language_callback(update: Update, context: ContextTypes.DEFAULT_TYPE):
|
||||
|
||||
# --- Webinar Checking Job ---
|
||||
|
||||
def get_webinar_key(name: str, url: str) -> str:
|
||||
"""Generate unique key for a webinar based on name and URL."""
|
||||
return f"{name}|{url}"
|
||||
def get_webinar_key(url: str) -> str:
|
||||
"""Generate unique key for a webinar based on URL."""
|
||||
return url
|
||||
|
||||
def get_stored_webinars() -> list:
|
||||
"""Get list of stored webinar keys from Redis."""
|
||||
@@ -378,9 +451,9 @@ def get_stored_webinars() -> list:
|
||||
return []
|
||||
|
||||
def store_webinars(webinar_keys: list):
|
||||
"""Store up to 5 most recent webinar keys in Redis."""
|
||||
# Keep only last 5
|
||||
webinar_keys = webinar_keys[-5:]
|
||||
"""Store up to 3 most recent webinar keys in Redis."""
|
||||
# Keep only last 3
|
||||
webinar_keys = webinar_keys[-3:]
|
||||
try:
|
||||
redis_client.set(KEY_WEBINAR_HISTORY, json.dumps(webinar_keys))
|
||||
logger.info(f"Stored {len(webinar_keys)} webinar(s) in history")
|
||||
@@ -515,7 +588,7 @@ async def check_webinars_job(context: ContextTypes.DEFAULT_TYPE):
|
||||
current_keys = []
|
||||
|
||||
for webinar in current_webinars:
|
||||
key = get_webinar_key(webinar['name'], webinar['url'])
|
||||
key = get_webinar_key(webinar['url'])
|
||||
current_keys.append(key)
|
||||
|
||||
if key not in stored_keys:
|
||||
@@ -535,6 +608,7 @@ async def check_webinars_job(context: ContextTypes.DEFAULT_TYPE):
|
||||
for sub_id in subscribers:
|
||||
try:
|
||||
# Build message in user's language
|
||||
# sub_id comes from redis set as string, convert to int for translation lookup
|
||||
webinar_items = "\n\n".join([
|
||||
t(int(sub_id), 'webinar_item', name=w['name'], url=w['url'])
|
||||
for w in new_webinars
|
||||
@@ -569,10 +643,12 @@ def main():
|
||||
|
||||
# Handlers
|
||||
app.add_handler(CommandHandler("start", start))
|
||||
app.add_handler(CommandHandler("stop", stop_command))
|
||||
app.add_handler(CommandHandler("help", help_command))
|
||||
app.add_handler(CommandHandler("language", language_command))
|
||||
app.add_handler(CommandHandler("adduser", add_user))
|
||||
app.add_handler(CommandHandler("removeuser", remove_user))
|
||||
app.add_handler(CommandHandler("clearhistory", clear_history))
|
||||
|
||||
# Callback handlers - language selection first, then admin panel
|
||||
app.add_handler(CallbackQueryHandler(language_callback, pattern="^lang_"))
|
||||
|
||||
+4
-1
@@ -1,3 +1,6 @@
|
||||
GITEA_POSTGRES_USER=
|
||||
GITEA_POSTGRES_PASSWORD=
|
||||
GITEA_POSTGRES_DB=gitea
|
||||
GITEA_POSTGRES_DB=gitea
|
||||
GITEA_SMTP_PASS=
|
||||
MAILER_ADDR=
|
||||
SERVICE_EMAIL=email.used.by.services@domain.tld
|
||||
+24
-17
@@ -2,6 +2,7 @@ services:
|
||||
server:
|
||||
image: docker.gitea.com/gitea:1.25.1
|
||||
container_name: gitea
|
||||
restart: always
|
||||
environment:
|
||||
- USER_UID=1000
|
||||
- USER_GID=1000
|
||||
@@ -13,45 +14,52 @@ services:
|
||||
- GITEA__database__NAME=gitea
|
||||
#Server
|
||||
- GITEA__server__ROOT_URL=https://gitea.forust.xyz
|
||||
- GITEA__server__SSH_DOMAIN=gitssh.forust.xyz
|
||||
- GITEA__server__SSH_PORT=2221
|
||||
restart: always
|
||||
networks:
|
||||
- gitea-db
|
||||
- traefik-proxy
|
||||
# Mailer
|
||||
- GITEA__mailer__ENABLED=true
|
||||
- GITEA__mailer__FROM=${SERVICE_EMAIL}
|
||||
- GITEA__mailer__SMTP_ADDR=${MAILER_ADDR}:465
|
||||
- GITEA__mailer__USER=${SERVICE_EMAIL}
|
||||
- GITEA__mailer__PASSWD=${GITEA_SMTP_PASS}
|
||||
- GITEA__mailer__PROTOCOL=SMTP
|
||||
- GITEA__service__REGISTER_EMAIL_CONFIRM=true
|
||||
- GITEA__service__ENABLE_NOTIFY_MAIL=true
|
||||
volumes:
|
||||
- ./gitea-data:/data
|
||||
- /etc/timezone:/etc/timezone:ro
|
||||
- /etc/localtime:/etc/localtime:ro
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.docker.network=traefik-proxy"
|
||||
- "traefik.docker.network=proxy"
|
||||
- "traefik.http.services.gitea.loadbalancer.server.port=3000"
|
||||
|
||||
# Prod Router
|
||||
- "traefik.http.routers.gitea.rule=Host(`gitea.forust.xyz`)"
|
||||
- "traefik.http.routers.gitea.entrypoints=websecure"
|
||||
- "traefik.http.routers.gitea.middlewares=security-headers@file"
|
||||
- "traefik.http.routers.gitea.service=gitea"
|
||||
- "traefik.http.routers.gitea.tls=true"
|
||||
- "traefik.http.services.gitea.loadbalancer.server.port=3000"
|
||||
|
||||
# Local Router
|
||||
- "traefik.http.routers.gitea-local.rule=Host(`gitea.workstation.internal`) || Host(`gitea.internal`)"
|
||||
- "traefik.http.routers.gitea-local.rule=Host(`gitea.workstation.internal`)"
|
||||
- "traefik.http.routers.gitea-local.entrypoints=websecure"
|
||||
- "traefik.http.routers.gitea-local.middlewares=security-headers@file"
|
||||
- "traefik.http.routers.gitea-local.service=gitea"
|
||||
- "traefik.http.routers.gitea-local.tls=true"
|
||||
|
||||
# Dev Router
|
||||
- "traefik.http.routers.gitea-dev.rule=Host(`gitea.gigaforust.internal`)"
|
||||
- "traefik.http.routers.gitea-dev.entrypoints=websecure"
|
||||
- "traefik.http.routers.gitea-dev.middlewares=security-headers@file"
|
||||
- "traefik.http.routers.gitea-dev.service=gitea"
|
||||
- "traefik.http.routers.gitea-dev.tls=true"
|
||||
# SSH Router
|
||||
- "traefik.tcp.services.gitea.loadbalancer.server.port=22"
|
||||
- "traefik.tcp.routers.gitea.entrypoints=ssh"
|
||||
- "traefik.tcp.routers.gitea.rule=HostSNI(`*`)"
|
||||
ports:
|
||||
- "2221:22"
|
||||
networks:
|
||||
- gitea-db
|
||||
- proxy
|
||||
depends_on:
|
||||
- db
|
||||
|
||||
db:
|
||||
image: docker.io/library/postgres:14
|
||||
restart: always
|
||||
@@ -59,13 +67,12 @@ services:
|
||||
- POSTGRES_USER=gitea
|
||||
- POSTGRES_PASSWORD=gitea
|
||||
- POSTGRES_DB=gitea
|
||||
networks:
|
||||
- gitea-db
|
||||
volumes:
|
||||
- ./gitea-db/:/var/lib/postgresql/data
|
||||
|
||||
networks:
|
||||
- gitea-db
|
||||
networks:
|
||||
gitea-db:
|
||||
external: false
|
||||
traefik-proxy:
|
||||
proxy:
|
||||
external: true
|
||||
|
||||
+5
-9
@@ -11,30 +11,26 @@ services:
|
||||
env_file: .env
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.docker.network=traefik-proxy"
|
||||
- "traefik.docker.network=proxy"
|
||||
# FIXME: traefik.services.glance.loadbalancer.server.port ??
|
||||
|
||||
# Prod Router
|
||||
- "traefik.http.routers.glance.rule=Host(`glance.forust.xyz`)"
|
||||
- "traefik.http.routers.glance.entrypoints=websecure"
|
||||
- "traefik.http.routers.glance.middlewares=security-headers@file"
|
||||
- "traefik.http.routers.glance.tls=true"
|
||||
|
||||
# Local Router
|
||||
- "traefik.http.routers.glance-local.rule=Host(`glance.workstation.internal`) || Host(`glance.internal`)"
|
||||
- "traefik.http.routers.glance-local.rule=Host(`glance.workstation.internal`)"
|
||||
- "traefik.http.routers.glance-local.entrypoints=websecure"
|
||||
- "traefik.http.routers.glance-local.middlewares=security-headers@file"
|
||||
- "traefik.http.routers.glance-local.tls=true"
|
||||
|
||||
# Dev Router
|
||||
- "traefik.http.routers.glance-dev.rule=Host(`glance.gigaforust.internal`)"
|
||||
- "traefik.http.routers.glance-dev.entrypoints=websecure"
|
||||
- "traefik.http.routers.glance-dev.middlewares=security-headers@file"
|
||||
- "traefik.http.routers.glance-dev.tls=true"
|
||||
networks:
|
||||
- traefik-proxy
|
||||
dns:
|
||||
- 1.1.1.1
|
||||
- 8.8.8.8
|
||||
- proxy
|
||||
networks:
|
||||
traefik-proxy:
|
||||
proxy:
|
||||
external: true
|
||||
@@ -0,0 +1,79 @@
|
||||
services:
|
||||
server:
|
||||
image: headscale/headscale:latest
|
||||
restart: unless-stopped
|
||||
command: serve
|
||||
networks:
|
||||
- proxy
|
||||
volumes:
|
||||
- ./config:/etc/headscale
|
||||
- data:/var/lib/headscale
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.docker.network=proxy"
|
||||
- "traefik.http.services.headscale.loadbalancer.server.port=8080"
|
||||
- "traefik.http.services.headscale-metrics.loadbalancer.server.port=9090"
|
||||
|
||||
## SERVICE
|
||||
# Prod Router
|
||||
- "traefik.http.routers.headscale.rule=Host(`hs.forust.xyz`)"
|
||||
- "traefik.http.routers.headscale.entrypoints=websecure"
|
||||
- "traefik.http.routers.headscale.service=headscale"
|
||||
- "traefik.http.routers.headscale.tls=true"
|
||||
# Local Router
|
||||
- "traefik.http.routers.headscale-local.rule=Host(`hs.workstation.internal`)"
|
||||
- "traefik.http.routers.headscale-local.entrypoints=websecure"
|
||||
- "traefik.http.routers.headscale-local.service=headscale"
|
||||
- "traefik.http.routers.headscale-local.tls=true"
|
||||
# Dev Router
|
||||
- "traefik.http.routers.headscale-dev.rule=Host(`hs.gigaforust.internal`)"
|
||||
- "traefik.http.routers.headscale-dev.entrypoints=websecure"
|
||||
- "traefik.http.routers.headscale-dev.service=headscale"
|
||||
- "traefik.http.routers.headscale-dev.tls=true"
|
||||
|
||||
## METRICS
|
||||
# Prod Router
|
||||
- "traefik.http.routers.headscale-metrics.rule=Host(`hs.forust.xyz`) && PathPrefix(`/metrics`)"
|
||||
- "traefik.http.routers.headscale-metrics.entrypoints=websecure"
|
||||
- "traefik.http.routers.headscale-metrics.service=headscale-metrics"
|
||||
- "traefik.http.routers.headscale-metrics.tls=true"
|
||||
# Local Router
|
||||
- "traefik.http.routers.headscale-metrics-local.rule=Host(`hs.workstation.internal`) && PathPrefix(`/metrics`)"
|
||||
- "traefik.http.routers.headscale-metrics-local.entrypoints=websecure"
|
||||
- "traefik.http.routers.headscale-metrics-local.service=headscale-metrics"
|
||||
- "traefik.http.routers.headscale-metrics-local.tls=true"
|
||||
# Dev Router
|
||||
- "traefik.http.routers.headscale-metrics-dev.rule=Host(`hs.gigaforust.internal`) && PathPrefix(`/metrics`)"
|
||||
- "traefik.http.routers.headscale-metrics-dev.entrypoints=websecure"
|
||||
- "traefik.http.routers.headscale-metrics-dev.service=headscale-metrics"
|
||||
- "traefik.http.routers.headscale-metrics-dev.tls=true"
|
||||
web:
|
||||
image: goodieshq/headscale-admin:latest
|
||||
restart: unless-stopped
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "treafik.docker.network=proxy"
|
||||
- "traefik.http.services.headscale-ui.loadbalancer.server.port=80"
|
||||
|
||||
# Prod Router
|
||||
- "traefik.http.routers.headscale-ui.rule=Host(`hs.forust.xyz`) && PathPrefix(`/admin`)"
|
||||
- "traefik.http.routers.headscale-ui.entrypoints=websecure"
|
||||
- "traefik.http.routers.headscale-ui.middlewares=security-chain@file"
|
||||
- "traefik.http.routers.headscale-ui.tls=true"
|
||||
# Local Router
|
||||
- "traefik.http.routers.headscale-ui-local.rule=Host(`hs.workstation.internal`) && PathPrefix(`/admin`)"
|
||||
- "traefik.http.routers.headscale-ui-local.entrypoints=websecure"
|
||||
- "traefik.http.routers.headscale-ui-local.middlewares=security-chain@file"
|
||||
- "traefik.http.routers.headscale-ui-local.tls=true"
|
||||
# Dev Router
|
||||
- "traefik.http.routers.headscale-ui-dev.rule=Host(`hs.gigaforust.internal`) && PathPrefix(`/admin`)"
|
||||
- "traefik.http.routers.headscale-ui-dev.entrypoints=websecure"
|
||||
- "traefik.http.routers.headscale-ui-dev.middlewares=security-chain@file"
|
||||
- "traefik.http.routers.headscale-ui-dev.tls=true"
|
||||
networks:
|
||||
- proxy
|
||||
volumes:
|
||||
data:
|
||||
networks:
|
||||
proxy:
|
||||
external: true
|
||||
@@ -0,0 +1,79 @@
|
||||
# https://wiki.serversatho.me/en/headscale
|
||||
|
||||
# # Prod server_url
|
||||
# server_url: https://hs.example.com
|
||||
# # Local server_url
|
||||
# server_url: https://hs.internal_domain.internal
|
||||
# # Dev server_url
|
||||
# server_url: https://hs.dev_internal_domain.internal
|
||||
listen_addr: 0.0.0.0:8080
|
||||
metrics_listen_addr: 127.0.0.1:9090
|
||||
grpc_listen_addr: 127.0.0.1:50443
|
||||
grpc_allow_insecure: false
|
||||
noise:
|
||||
private_key_path: /var/lib/headscale/noise_private.key
|
||||
prefixes:
|
||||
v4: 100.64.0.0/10
|
||||
v6: fd7a:115c:a1e0::/48
|
||||
allocation: sequential
|
||||
derp:
|
||||
server:
|
||||
enabled: true
|
||||
region_id: 999
|
||||
region_code: "headscale"
|
||||
region_name: "Headscale Embedded DERP"
|
||||
stun_listen_addr: "0.0.0.0:3478"
|
||||
private_key_path: /var/lib/headscale/derp_server_private.key
|
||||
automatically_add_embedded_derp_region: true
|
||||
ipv4: 1.2.3.4
|
||||
ipv6: 2001:db8::1
|
||||
urls:
|
||||
- https://controlplane.tailscale.com/derpmap/default
|
||||
paths: []
|
||||
auto_update_enabled: true
|
||||
update_frequency: 24h
|
||||
disable_check_updates: false
|
||||
ephemeral_node_inactivity_timeout: 30m
|
||||
database:
|
||||
type: sqlite
|
||||
debug: false
|
||||
gorm:
|
||||
prepare_stmt: true
|
||||
parameterized_queries: true
|
||||
skip_err_record_not_found: true
|
||||
slow_threshold: 1000
|
||||
sqlite:
|
||||
path: /var/lib/headscale/db.sqlite
|
||||
write_ahead_log: true
|
||||
wal_autocheckpoint: 1000
|
||||
acme_url: https://acme-v02.api.letsencrypt.org/directory
|
||||
acme_email: ""
|
||||
tls_letsencrypt_hostname: ""
|
||||
tls_letsencrypt_cache_dir: /var/lib/headscale/cache
|
||||
tls_letsencrypt_challenge_type: HTTP-01
|
||||
tls_letsencrypt_listen: ":http"
|
||||
tls_cert_path: ""
|
||||
tls_key_path: ""
|
||||
log:
|
||||
format: text
|
||||
level: info
|
||||
policy:
|
||||
mode: database
|
||||
path: ""
|
||||
dns:
|
||||
magic_dns: true
|
||||
base_domain: example.com
|
||||
nameservers:
|
||||
global:
|
||||
- 1.1.1.1
|
||||
- 1.0.0.1
|
||||
- 2606:4700:4700::1111
|
||||
- 2606:4700:4700::1001
|
||||
split: {}
|
||||
search_domains: []
|
||||
extra_records: []
|
||||
unix_socket: /var/run/headscale/headscale.sock
|
||||
unix_socket_permission: "0770"
|
||||
logtail:
|
||||
enabled: false
|
||||
randomize_client_port: false
|
||||
@@ -1,39 +0,0 @@
|
||||
services:
|
||||
forust-homepage:
|
||||
build: .
|
||||
ports:
|
||||
- "8085:80"
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- ./files:/usr/share/nginx/html
|
||||
networks:
|
||||
- traefik-proxy
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.docker.network=traefik-proxy"
|
||||
|
||||
# Prod Router
|
||||
- "traefik.http.routers.forust-homepage.rule=Host(`forust.xyz`)"
|
||||
- "traefik.http.routers.forust-homepage.entrypoints=websecure"
|
||||
- "traefik.http.routers.forust-homepage.middlewares=security-headers@file"
|
||||
- "traefik.http.routers.forust-homepage.service=forust-homepage"
|
||||
- "traefik.http.routers.forust-homepage.tls=true"
|
||||
- "traefik.http.services.forust-homepage.loadbalancer.server.port=80"
|
||||
|
||||
# Local Router
|
||||
- "traefik.http.routers.forust-homepage-local.rule=Host(`landing.workstation.internal`) || Host(`landing.internal`)"
|
||||
- "traefik.http.routers.forust-homepage-local.entrypoints=websecure"
|
||||
- "traefik.http.routers.forust-homepage-local.middlewares=security-headers@file"
|
||||
- "traefik.http.routers.forust-homepage-local.service=forust-homepage"
|
||||
- "traefik.http.routers.forust-homepage-local.tls=true"
|
||||
|
||||
# Dev Router
|
||||
- "traefik.http.routers.forust-homepage-dev.rule=Host(`landing.gigaforust.internal`)"
|
||||
- "traefik.http.routers.forust-homepage-dev.entrypoints=websecure"
|
||||
- "traefik.http.routers.forust-homepage-dev.middlewares=security-headers@file"
|
||||
- "traefik.http.routers.forust-homepage-dev.service=forust-homepage"
|
||||
- "traefik.http.routers.forust-homepage-dev.tls=true"
|
||||
|
||||
networks:
|
||||
traefik-proxy:
|
||||
external: true
|
||||
@@ -0,0 +1,10 @@
|
||||
# everyone use that
|
||||
FROM nginx:alpine
|
||||
|
||||
RUN rm -rf /usr/share/nginx/html/*
|
||||
|
||||
COPY ./forust_files /usr/share/nginx/html
|
||||
|
||||
EXPOSE 80
|
||||
# Start
|
||||
CMD ["nginx", "-g", "daemon off;"]
|
||||
@@ -3,7 +3,7 @@ FROM nginx:alpine
|
||||
|
||||
RUN rm -rf /usr/share/nginx/html/*
|
||||
|
||||
COPY ./files /usr/share/nginx/html
|
||||
COPY ./xdfnx_files /usr/share/nginx/html
|
||||
|
||||
EXPOSE 80
|
||||
# Start
|
||||
@@ -0,0 +1,66 @@
|
||||
services:
|
||||
forust:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile.forust
|
||||
# ports:
|
||||
# - "8085:80"
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- ./forust_files:/usr/share/nginx/html
|
||||
networks:
|
||||
- proxy
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.docker.network=proxy"
|
||||
- "traefik.http.services.forust-homepage.loadbalancer.server.port=80"
|
||||
|
||||
# Prod Router
|
||||
- "traefik.http.routers.forust-homepage.rule=Host(`forust.xyz`)"
|
||||
- "traefik.http.routers.forust-homepage.entrypoints=websecure"
|
||||
- "traefik.http.routers.forust-homepage.middlewares=security-headers@file"
|
||||
- "traefik.http.routers.forust-homepage.tls=true"
|
||||
# Local Router
|
||||
- "traefik.http.routers.forust-homepage-local.rule=Host(`landing.workstation.internal`)"
|
||||
- "traefik.http.routers.forust-homepage-local.entrypoints=websecure"
|
||||
- "traefik.http.routers.forust-homepage-local.middlewares=security-headers@file"
|
||||
- "traefik.http.routers.forust-homepage-local.tls=true"
|
||||
# Dev Router
|
||||
- "traefik.http.routers.forust-homepage-dev.rule=Host(`landing.gigaforust.internal`)"
|
||||
- "traefik.http.routers.forust-homepage-dev.entrypoints=websecure"
|
||||
- "traefik.http.routers.forust-homepage-dev.middlewares=security-headers@file"
|
||||
- "traefik.http.routers.forust-homepage-dev.tls=true"
|
||||
xdfnx:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile.xdfnx
|
||||
restart: unless-stopped
|
||||
# ports:
|
||||
# - "8086:80"
|
||||
volumes:
|
||||
- ./xdfnx_files:/usr/share/nginx/html
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.docker.network=proxy"
|
||||
- "traefik.http.services.xdfnx-homepage.loadbalancer.server.port=80"
|
||||
|
||||
# Prod Router
|
||||
- "traefik.http.routers.xdfnx.rule=Host(`xdfnx.cfd`)"
|
||||
- "traefik.http.routers.xdfnx.entrypoints=websecure"
|
||||
- "traefik.http.routers.xdfnx.middlewares=security-headers@file"
|
||||
- "traefik.http.routers.xdfnx.tls=true"
|
||||
# Local Router
|
||||
- "traefik.http.routers.xdfnx-local.rule=Host(`xdfnx.workstation.internal`)"
|
||||
- "traefik.http.routers.xdfnx-local.entrypoints=websecure"
|
||||
- "traefik.http.routers.xdfnx-local.middlewares=security-headers@file"
|
||||
- "traefik.http.routers.xdfnx-local.tls=true"
|
||||
# Dev Router
|
||||
- "traefik.http.routers.xdfnx-dev.rule=Host(`xdfnx.gigaforust.internal`)"
|
||||
- "traefik.http.routers.xdfnx-dev.entrypoints=websecure"
|
||||
- "traefik.http.routers.xdfnx-dev.middlewares=security-headers@file"
|
||||
- "traefik.http.routers.xdfnx-dev.tls=true"
|
||||
networks:
|
||||
- proxy
|
||||
networks:
|
||||
proxy:
|
||||
external: true
|
||||
@@ -41,7 +41,14 @@
|
||||
</li>
|
||||
<li>
|
||||
<i class="fas fa-envelope"></i>
|
||||
<a href="mailto:forust@forust.xyz">forust@forust.xyz</a>
|
||||
<a href="mailto:forust@forust.xyz">mail/contact@forust.xyz</a>
|
||||
</li>
|
||||
<li>
|
||||
<i class="fa-solid fa-key"></i>
|
||||
<a href=".well-known/pgp-key.asc">security/PGP Key</a>
|
||||
</li>
|
||||
<li>
|
||||
<p class="comment"># PGP Key Fingerprint: A777 7CB7 D9C4 0A97 443D CCF0 7A3D A455 F820 5B82</p>
|
||||
</li>
|
||||
</ul>
|
||||
</section>
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 42 KiB |
File diff suppressed because it is too large
Load Diff
+10
-16
@@ -1,7 +1,7 @@
|
||||
services:
|
||||
metube:
|
||||
image: ghcr.io/alexta69/metube
|
||||
# container_name: metube
|
||||
container_name: metube
|
||||
restart: unless-stopped
|
||||
# ports:
|
||||
# - "8081:8081"
|
||||
@@ -13,33 +13,27 @@ services:
|
||||
volumes:
|
||||
- ./MeTube_downloads:/downloads
|
||||
labels:
|
||||
- traefik.enable=true
|
||||
- "traefik.docker.network=traefik-proxy"
|
||||
- "traefik.enable=true"
|
||||
- "traefik.docker.network=proxy"
|
||||
- "traefik.http.services.metube.loadbalancer.server.port=8081"
|
||||
|
||||
# Prod Router
|
||||
- "traefik.http.routers.metube.rule=Host(`metube.forust.xyz`)"
|
||||
- "traefik.http.routers.metube.entrypoints=websecure"
|
||||
- "traefik.http.routers.metube.middlewares=security-headers@file,metube-auth@file"
|
||||
- "traefik.http.routers.metube.service=metube"
|
||||
- "traefik.http.routers.metube.middlewares=security-chain@file"
|
||||
- "traefik.http.routers.metube.tls=true"
|
||||
- "traefik.http.services.metube.loadbalancer.server.port=8081"
|
||||
|
||||
# Local Router
|
||||
- "traefik.http.routers.metube-local.rule=Host(`metube.workstation.internal`) || Host(`metube.internal`)"
|
||||
- "traefik.http.routers.metube-local.rule=Host(`metube.workstation.internal`))"
|
||||
- "traefik.http.routers.metube-local.entrypoints=websecure"
|
||||
- "traefik.http.routers.metube-local.middlewares=security-headers@file,metube-auth@file"
|
||||
- "traefik.http.routers.metube-local.service=metube"
|
||||
- "traefik.http.routers.metube-local.middlewares=security-headers@file"
|
||||
- "traefik.http.routers.metube-local.tls=true"
|
||||
|
||||
# Dev Router
|
||||
- "traefik.http.routers.metube-dev.rule=Host(`metube.gigaforust.internal`)"
|
||||
- "traefik.http.routers.metube-dev.entrypoints=websecure"
|
||||
- "traefik.http.routers.metube-dev.middlewares=security-headers@file,metube-auth@file"
|
||||
- "traefik.http.routers.metube-dev.service=metube"
|
||||
- "traefik.http.routers.metube-dev.middlewares=security-chain@file"
|
||||
- "traefik.http.routers.metube-dev.tls=true"
|
||||
|
||||
networks:
|
||||
- traefik-proxy
|
||||
- proxy
|
||||
networks:
|
||||
traefik-proxy:
|
||||
proxy:
|
||||
external: true
|
||||
|
||||
+3
-3
@@ -23,11 +23,11 @@ services:
|
||||
- 1.1.1.1
|
||||
- 8.8.8.8
|
||||
networks:
|
||||
- traefik-proxy
|
||||
- proxy
|
||||
- n8n
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.docker.network=traefik-proxy"
|
||||
- "traefik.docker.network=proxy"
|
||||
|
||||
# Prod Router
|
||||
- "traefik.http.routers.n8n.rule=Host(`n8n.forust.xyz`)"
|
||||
@@ -58,5 +58,5 @@ services:
|
||||
networks:
|
||||
n8n:
|
||||
external: false
|
||||
traefik-proxy:
|
||||
proxy:
|
||||
external: true
|
||||
|
||||
+11
-19
@@ -1,6 +1,6 @@
|
||||
services:
|
||||
nextcloud-aio-mastercontainer:
|
||||
image: ghcr.io/nextcloud-releases/all-in-one:latest
|
||||
image: ghcr.io/nextcloud-releases/all-in-one:beta
|
||||
init: true # This setting makes sure that signals from main process inside the container are correctly forwarded to children. See https://docs.docker.com/reference/compose-file/services/#init
|
||||
restart: unless-stopped
|
||||
container_name: nextcloud-aio-mastercontainer # Do not change
|
||||
@@ -9,8 +9,7 @@ services:
|
||||
- /var/run/docker.sock:/var/run/docker.sock:ro
|
||||
networks:
|
||||
- nextcloud-aio
|
||||
- traefik-proxy # Optional: Connects the mastercontainer to the traefik-proxy network in order to make the built-in reverse proxy detection work. See https://github.com/nextcloud/all-in-one/blob/main/reverse-proxy.md
|
||||
|
||||
- proxy # Optional: Connects the mastercontainer to the proxy network in order to make the built-in reverse proxy detection work. See https://github.com/nextcloud/all-in-one/blob/main/reverse-proxy.md
|
||||
# ports:
|
||||
# - 8081:80 # may be removed if under reverse-proxy
|
||||
# - 8443:8443
|
||||
@@ -18,49 +17,42 @@ services:
|
||||
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.docker.network=traefik-proxy"
|
||||
|
||||
- "traefik.docker.network=proxy"
|
||||
# AIO Services configuration
|
||||
- "traefik.http.services.nextcloud-aio.loadbalancer.server.port=8080"
|
||||
- "traefik.http.services.nextcloud-aio.loadbalancer.server.scheme=https"
|
||||
- "traefik.http.services.nextcloud-aio.loadbalancer.serverstransport=insecureTransport@file"
|
||||
|
||||
# Prod Router
|
||||
# - "traefik.http.routers.nextcloud-aio.rule=Host(`nextcloud-aio.forust.xyz`)"
|
||||
# - "traefik.http.routers.nextcloud-aio.rule=Host(`naio.forust.xyz`)"
|
||||
# - "traefik.http.routers.nextcloud-aio.entrypoints=websecure"
|
||||
# - "traefik.http.routers.nextcloud-aio.middlewares=security-headers"
|
||||
# - "traefik.http.routers.nextcloud-aio.middlewares=security-chain@file"
|
||||
# - "traefik.http.routers.nextcloud-aio.service=nextcloud-aio"
|
||||
# - "traefik.http.routers.nextcloud-aio.tls=true"
|
||||
|
||||
# Local Router
|
||||
- "traefik.http.routers.nextcloud-aio-local.rule=Host(`nextcloud-aio.workstation.internal`) || Host(`nextcloud-aio.internal`)"
|
||||
- "traefik.http.routers.nextcloud-aio-local.rule=Host(`naio.workstation.internal`)"
|
||||
- "traefik.http.routers.nextcloud-aio-local.entrypoints=websecure"
|
||||
- "traefik.http.routers.nextcloud-aio-local.middlewares=security-headers@file"
|
||||
- "traefik.http.routers.nextcloud-aio-local.service=nextcloud-aio"
|
||||
- "traefik.http.routers.nextcloud-aio-local.tls=true"
|
||||
|
||||
# Dev Router
|
||||
- "traefik.http.routers.nextcloud-aio-dev.rule=Host(`nextcloud-aio.gigaforust.internal`)"
|
||||
- "traefik.http.routers.nextcloud-aio-dev.rule=Host(`naio.gigaforust.internal`)"
|
||||
- "traefik.http.routers.nextcloud-aio-dev.entrypoints=websecure"
|
||||
- "traefik.http.routers.nextcloud-aio-dev.middlewares=security-headers@file"
|
||||
- "traefik.http.routers.nextcloud-aio-dev.service=nextcloud-aio"
|
||||
- "traefik.http.routers.nextcloud-aio-dev.tls=true"
|
||||
|
||||
# Glanceapp/glance config
|
||||
# Glance Metadata
|
||||
- glance.name=Nextcloud
|
||||
# - glance.icon=si:nextcloud
|
||||
- glance.url=https://nextcloud.forust.xyz/
|
||||
- glance.description=Nextcloud is a suite of client-server software for creating and using file hosting services.
|
||||
|
||||
environment:
|
||||
AIO_DISABLE_BACKUP_SECTION: false
|
||||
APACHE_PORT: 11000 # Is needed when running behind a web server or reverse proxy (like Apache, Nginx, Caddy, Cloudflare Tunnel and else). See https://github.com/nextcloud/all-in-one/blob/main/reverse-proxy.md
|
||||
APACHE_IP_BINDING: 0.0.0.0 # Configure when going with reverse-proxy https://github.com/nextcloud/all-in-one/blob/main/reverse-proxy.md
|
||||
APACHE_ADDITIONAL_NETWORK: traefik-proxy # (Optional) Connect the apache container to an additional docker network. When going with reverse-proxy. See https://github.com/nextcloud/all-in-one/blob/main/reverse-proxy.md
|
||||
APACHE_ADDITIONAL_NETWORK: proxy # (Optional) Connect the apache container to an additional docker network. When going with reverse-proxy. See https://github.com/nextcloud/all-in-one/blob/main/reverse-proxy.md
|
||||
BORG_RETENTION_POLICY: --keep-within=7d --keep-weekly=4 --keep-monthly=6 # Backup retention See https://github.com/nextcloud/all-in-one#how-to-adjust-borgs-retention-policy
|
||||
COLLABORA_SECCOMP_DISABLED: false # Setting this to true allows to disable Collabora's Seccomp feature. See https://github.com/nextcloud/all-in-one#how-to-disable-collaboras-seccomp-feature
|
||||
FULLTEXTSEARCH_JAVA_OPTIONS: "-Xms1024M -Xmx1024M" # adjust fulltextsearch java options. https://github.com/nextcloud/all-in-one#how-to-adjust-the-fulltextsearch-java-options
|
||||
NEXTCLOUD_DATADIR: /media/forust/nextcloud/ncdata # Allows to set the host directory for Nextcloud's datadir. ⚠️⚠️⚠️ Warning: do not set or adjust this value after the initial Nextcloud installation is done! See https://github.com/nextcloud/all-in-one#how-to-change-the-default-location-of-nextclouds-datadir
|
||||
NEXTCLOUD_DATADIR: /mnt/nextcloud/ncdata # Allows to set the host directory for Nextcloud's datadir. ⚠️⚠️⚠️ Warning: do not set or adjust this value after the initial Nextcloud installation is done! See https://github.com/nextcloud/all-in-one#how-to-change-the-default-location-of-nextclouds-datadir
|
||||
NEXTCLOUD_MOUNT: /mnt/ # Allows the Nextcloud container to access the chosen directory on the host. See https://github.com/nextcloud/all-in-one#how-to-allow-the-nextcloud-container-to-access-directories-on-the-host
|
||||
NEXTCLOUD_UPLOAD_LIMIT: 16G # https://github.com/nextcloud/all-in-one#how-to-adjust-the-upload-limit-for-nextcloud
|
||||
NEXTCLOUD_MAX_TIME: 7200 # Max uploading time See https://github.com/nextcloud/all-in-one#how-to-adjust-the-max-execution-time-for-nextcloud
|
||||
@@ -76,7 +68,7 @@ services:
|
||||
# WATCHTOWER_DOCKER_SOCKET_PATH: /var/run/docker.sock # Needs to be specified if the docker socket on the host is not located in the default '/var/run/docker.sock'. For macos it needs to be '/var/run/docker.sock'
|
||||
|
||||
networks:
|
||||
traefik-proxy:
|
||||
proxy:
|
||||
external: true
|
||||
nextcloud-aio:
|
||||
driver: bridge
|
||||
|
||||
+7
-14
@@ -50,7 +50,7 @@ x-secret-key: &penpot-secret-key
|
||||
|
||||
networks:
|
||||
penpot:
|
||||
traefik-proxy:
|
||||
proxy:
|
||||
external: true
|
||||
|
||||
volumes:
|
||||
@@ -86,8 +86,8 @@ services:
|
||||
penpot-frontend:
|
||||
image: "penpotapp/frontend:${PENPOT_VERSION:-latest}"
|
||||
restart: always
|
||||
ports:
|
||||
- 9001:8080
|
||||
# ports:
|
||||
# - 9001:8080
|
||||
|
||||
volumes:
|
||||
- penpot_assets:/opt/data/assets
|
||||
@@ -98,37 +98,30 @@ services:
|
||||
|
||||
networks:
|
||||
- penpot
|
||||
- traefik-proxy
|
||||
- proxy
|
||||
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.docker.network=traefik-proxy"
|
||||
- "traefik.docker.network=proxy"
|
||||
- "traefik.http.services.penpot.loadbalancer.server.port=8080"
|
||||
|
||||
# Prod Router
|
||||
- "traefik.http.routers.penpot.rule=Host(`penpot.forust.xyz`)"
|
||||
- "traefik.http.routers.penpot.entrypoints=websecure"
|
||||
- "traefik.http.routers.penpot.middlewares=security-headers@file"
|
||||
- "traefik.http.routers.penpot.service=penpot"
|
||||
- "traefik.http.routers.penpot.tls=true"
|
||||
- "traefik.http.services.penpot.loadbalancer.server.port=8080"
|
||||
|
||||
# Local Router
|
||||
- "traefik.http.routers.penpot-local.rule=Host(`penpot.workstation.internal`) || Host(`penpot.internal`)"
|
||||
- "traefik.http.routers.penpot-local.rule=Host(`penpot.workstation.internal`)"
|
||||
- "traefik.http.routers.penpot-local.entrypoints=websecure"
|
||||
- "traefik.http.routers.penpot-local.middlewares=security-headers@file"
|
||||
- "traefik.http.routers.penpot-local.service=penpot"
|
||||
- "traefik.http.routers.penpot-local.tls=true"
|
||||
|
||||
# Dev Router
|
||||
- "traefik.http.routers.penpot-dev.rule=Host(`penpot.gigaforust.internal`)"
|
||||
- "traefik.http.routers.penpot-dev.entrypoints=websecure"
|
||||
- "traefik.http.routers.penpot-dev.middlewares=security-headers@file"
|
||||
- "traefik.http.routers.penpot-dev.service=penpot"
|
||||
- "traefik.http.routers.penpot-dev.tls=true"
|
||||
|
||||
environment:
|
||||
<<: [ *penpot-flags, *penpot-http-body-size ]
|
||||
|
||||
penpot-backend:
|
||||
image: "penpotapp/backend:${PENPOT_VERSION:-latest}"
|
||||
restart: always
|
||||
|
||||
+12
-21
@@ -1,54 +1,45 @@
|
||||
services:
|
||||
portainer:
|
||||
container_name: portainer
|
||||
image: portainer/portainer-ce:latest
|
||||
container_name: portainer
|
||||
restart: always
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
- ./portainer_data:/data
|
||||
- data:/data
|
||||
ports:
|
||||
- 9443:9443
|
||||
# - 8000:8000 # Remove if you do not intend to use Edge Agents
|
||||
networks:
|
||||
- traefik-proxy
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.docker.network=traefik-proxy"
|
||||
- "traefik.docker.network=proxy"
|
||||
- "traefik.http.services.portainer.loadbalancer.server.port=9443"
|
||||
- "traefik.http.services.portainer.loadbalancer.server.scheme=https"
|
||||
- "traefik.http.services.portainer.loadbalancer.serverstransport=insecureTransport@file"
|
||||
|
||||
# Prod Router
|
||||
- "traefik.http.routers.portainer.rule=Host(`portainer.forust.xyz`)"
|
||||
- "traefik.http.routers.portainer.entrypoints=websecure"
|
||||
- "traefik.http.routers.portainer.middlewares=security-headers@file"
|
||||
- "traefik.http.routers.portainer.service=portainer"
|
||||
- "traefik.http.routers.portainer.tls=true"
|
||||
- "traefik.http.services.portainer.loadbalancer.server.port=9443"
|
||||
- "traefik.http.services.portainer.loadbalancer.server.scheme=https"
|
||||
- "traefik.http.services.portainer.loadbalancer.serverstransport=insecureTransport@file"
|
||||
|
||||
# Local Router
|
||||
- "traefik.http.routers.portainer-local.rule=Host(`portainer.workstation.internal`) || Host(`portainer.internal`)"
|
||||
- "traefik.http.routers.portainer-local.rule=Host(`portainer.workstation.internal`)"
|
||||
- "traefik.http.routers.portainer-local.entrypoints=websecure"
|
||||
- "traefik.http.routers.portainer-local.middlewares=security-headers@file"
|
||||
- "traefik.http.routers.portainer-local.service=portainer"
|
||||
- "traefik.http.routers.portainer-local.tls=true"
|
||||
|
||||
# Dev Router
|
||||
- "traefik.http.routers.portainer-dev.rule=Host(`portainer.gigaforust.internal`)"
|
||||
- "traefik.http.routers.portainer-dev.entrypoints=websecure"
|
||||
- "traefik.http.routers.portainer-dev.middlewares=security-headers@file"
|
||||
- "traefik.http.routers.portainer-dev.service=portainer"
|
||||
- "traefik.http.routers.portainer-dev.tls=true"
|
||||
|
||||
# Glance Metadata
|
||||
- glance.name=Portainer
|
||||
- glance.url=https://portainer.forust.xyz/
|
||||
- glance.description=Portainer is a lightweight management UI which allows you to easily manage your Docker environments.
|
||||
|
||||
networks:
|
||||
- proxy
|
||||
volumes:
|
||||
portainer_data:
|
||||
name: portainer_data
|
||||
|
||||
data:
|
||||
networks:
|
||||
default:
|
||||
name: portainer_network
|
||||
traefik-proxy:
|
||||
proxy:
|
||||
external: true
|
||||
|
||||
+9
-17
@@ -3,44 +3,36 @@ services:
|
||||
image: ghcr.io/lukegus/termix:latest
|
||||
container_name: termix
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- "3331:8080"
|
||||
# ports:
|
||||
# - "3331:8080"
|
||||
volumes:
|
||||
- ./termix-data:/app/data
|
||||
- data:/app/data
|
||||
environment:
|
||||
PORT: "8080"
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.docker.network=traefik-proxy"
|
||||
- "traefik.docker.network=proxy"
|
||||
- "traefik.http.services.termix.loadbalancer.server.port=8080"
|
||||
|
||||
# Prod Router
|
||||
- "traefik.http.routers.termix.rule=Host(`termix.forust.xyz`)"
|
||||
- "traefik.http.routers.termix.entrypoints=websecure"
|
||||
- "traefik.http.routers.termix.middlewares=security-headers@file"
|
||||
- "traefik.http.routers.termix.service=termix"
|
||||
- "traefik.http.routers.termix.tls=true"
|
||||
- "traefik.http.services.termix.loadbalancer.server.port=8080"
|
||||
|
||||
# Local Router
|
||||
- "traefik.http.routers.termix-local.rule=Host(`termix.workstation.internal`) || Host(`termix.internal`)"
|
||||
- "traefik.http.routers.termix-local.rule=Host(`termix.workstation.internal`)"
|
||||
- "traefik.http.routers.termix-local.entrypoints=websecure"
|
||||
- "traefik.http.routers.termix-local.middlewares=security-headers@file"
|
||||
- "traefik.http.routers.termix-local.service=termix"
|
||||
- "traefik.http.routers.termix-local.tls=true"
|
||||
|
||||
# Dev Router
|
||||
- "traefik.http.routers.termix-dev.rule=Host(`termix.gigaforust.internal`)"
|
||||
- "traefik.http.routers.termix-dev.entrypoints=websecure"
|
||||
- "traefik.http.routers.termix-dev.middlewares=security-headers@file"
|
||||
- "traefik.http.routers.termix-dev.service=termix"
|
||||
- "traefik.http.routers.termix-dev.tls=true"
|
||||
networks:
|
||||
- traefik-proxy
|
||||
|
||||
- proxy
|
||||
networks:
|
||||
traefik-proxy:
|
||||
proxy:
|
||||
external: true
|
||||
|
||||
volumes:
|
||||
termix-data:
|
||||
driver: local
|
||||
data:
|
||||
@@ -0,0 +1,3 @@
|
||||
# ===================================
|
||||
# Traefik envs
|
||||
EMAIL=bobrovod@national.shitposting.agency
|
||||
+31
-39
@@ -11,7 +11,7 @@ services:
|
||||
# Providers
|
||||
- "--providers.docker=true"
|
||||
- "--providers.docker.exposedbydefault=false"
|
||||
- "--providers.docker.network=traefik-proxy"
|
||||
- "--providers.docker.network=proxy"
|
||||
- "--providers.file.directory=/etc/traefik/dynamic"
|
||||
- "--providers.file.watch=true"
|
||||
|
||||
@@ -23,69 +23,61 @@ services:
|
||||
- "--entryPoints.web.http.redirections.entryPoint.scheme=https"
|
||||
- "--entryPoints.ssh.address=:2221"
|
||||
|
||||
# Let's Encrypt STAGING. CURRENTLY USING CF ORIGIN CA INSTEAD
|
||||
# - "--certificatesresolvers.letsencrypt.acme.email=${EMAIL}"
|
||||
# - "--certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme.json"
|
||||
# Let's Encrypt
|
||||
- "--certificatesresolvers.letsencrypt.acme.email=${EMAIL}"
|
||||
- "--certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme.json"
|
||||
- "--certificatesresolvers.letsencrypt.acme.httpchallenge=true"
|
||||
- "--certificatesresolvers.letsencrypt.acme.httpchallenge.entrypoint=web"
|
||||
# # STAGING
|
||||
# - "--certificatesresolvers.letsencrypt.acme.caserver=https://acme-staging-v02.api.letsencrypt.org/directory"
|
||||
# - "--certificatesresolvers.letsencrypt.acme.httpchallenge=true"
|
||||
# - "--certificatesresolvers.letsencrypt.acme.httpchallenge.entrypoint=web"
|
||||
|
||||
# Cloudflare
|
||||
- "--entryPoints.web.forwardedHeaders.trustedIPs=173.245.48.0/20,103.21.244.0/22,103.22.200.0/22,103.31.4.0/22,141.101.64.0/18,108.162.192.0/18,190.93.240.0/20,188.114.96.0/20,197.234.240.0/22,198.41.128.0/17,162.158.0.0/15,104.16.0.0/13,104.24.0.0/14,172.64.0.0/13,131.0.72.0/22"
|
||||
- "--entryPoints.websecure.forwardedHeaders.trustedIPs=173.245.48.0/20,103.21.244.0/22,103.22.200.0/22,103.31.4.0/22,141.101.64.0/18,108.162.192.0/18,190.93.240.0/20,188.114.96.0/20,197.234.240.0/22,198.41.128.0/17,162.158.0.0/15,104.16.0.0/13,104.24.0.0/14,172.64.0.0/13,131.0.72.0/22"
|
||||
|
||||
# Logging
|
||||
- "--log.level=INFO"
|
||||
- "--log.filePath=/var/log/traefik/traefik.log"
|
||||
- "--accesslog=true"
|
||||
- "--accesslog.filepath=/var/log/traefik/access.log"
|
||||
|
||||
|
||||
# # Logging
|
||||
# - "--log.level=INFO"
|
||||
# - "--log.filePath=/var/log/traefik/traefik.log"
|
||||
# - "--accesslog=true"
|
||||
# - "--accesslog.filepath=/var/log/traefik/access.log"
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.docker.network=traefik-proxy"
|
||||
|
||||
# Prod Router (Dashboard) - DISABLED per user request
|
||||
# - "traefik.http.routers.traefik-dashboard.rule=Host(`traefik.forust.xyz`)"
|
||||
# - "traefik.http.routers.traefik-dashboard.entrypoints=websecure"
|
||||
# - "traefik.http.routers.traefik-dashboard.middlewares=auth,security-headers"
|
||||
# - "traefik.http.routers.traefik-dashboard.service=api@internal"
|
||||
# - "traefik.http.routers.traefik-dashboard.tls=true"
|
||||
- "traefik.docker.network=proxy"
|
||||
|
||||
# Prod Router (Dash)
|
||||
- "traefik.http.routers.traefik-dashboard.rule=Host(`traefik.forust.xyz`)"
|
||||
- "traefik.http.routers.traefik-dashboard.entrypoints=websecure"
|
||||
- "traefik.http.routers.traefik-dashboard.middlewares=security-chain@file"
|
||||
- "traefik.http.routers.traefik-dashboard.service=api@internal"
|
||||
- "traefik.http.routers.traefik-dashboard.tls=true"
|
||||
# Local Router
|
||||
- "traefik.http.routers.traefik-dashboard-local.rule=Host(`traefik.workstation.internal`) || Host(`traefik.internal`)"
|
||||
- "traefik.http.routers.traefik-dashboard-local.rule=Host(`traefik.workstation.internal`)"
|
||||
- "traefik.http.routers.traefik-dashboard-local.entrypoints=websecure"
|
||||
- "traefik.http.routers.traefik-dashboard-local.middlewares=auth@file,security-headers@file"
|
||||
- "traefik.http.routers.traefik-dashboard-local.middlewares=security-headers@file"
|
||||
- "traefik.http.routers.traefik-dashboard-local.service=api@internal"
|
||||
- "traefik.http.routers.traefik-dashboard-local.tls=true"
|
||||
|
||||
# Dev Router
|
||||
- "traefik.http.routers.traefik-dashboard-dev.rule=Host(`traefik.gigaforust.internal`)"
|
||||
- "traefik.http.routers.traefik-dashboard-dev.entrypoints=websecure"
|
||||
- "traefik.http.routers.traefik-dashboard-dev.middlewares=security-headers@file"
|
||||
- "traefik.http.routers.traefik-dashboard-dev.middlewares=security-chain@file"
|
||||
- "traefik.http.routers.traefik-dashboard-dev.service=api@internal"
|
||||
- "traefik.http.routers.traefik-dashboard-dev.tls=true"
|
||||
|
||||
# Glance Metadata
|
||||
- glance.name=Traefik
|
||||
- glance.url=https://traefik.forust.xyz/
|
||||
- glance.description=Traefik is a modern reverse proxy and load balancer
|
||||
|
||||
ports:
|
||||
- "80:80"
|
||||
- "443:443"
|
||||
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock:ro
|
||||
- ./dynamic:/etc/traefik/dynamic:ro
|
||||
- ./certs:/certs:ro
|
||||
- ./logs:/var/log/traefik
|
||||
# - ./traefik/letsencrypt:/letsencrypt
|
||||
|
||||
- ./letsencrypt:/letsencrypt
|
||||
ports:
|
||||
- "80:80"
|
||||
- "443:443"
|
||||
networks:
|
||||
- traefik-proxy
|
||||
|
||||
environment:
|
||||
- TZ=Europe/Bratislava
|
||||
|
||||
- proxy
|
||||
networks:
|
||||
traefik-proxy:
|
||||
external: true
|
||||
proxy:
|
||||
external: true
|
||||
@@ -0,0 +1,23 @@
|
||||
http:
|
||||
routers:
|
||||
fs1-public:
|
||||
rule: "Host(`fs1.domain.xyz`)"
|
||||
entrypoints:
|
||||
- websecure
|
||||
service: fs1
|
||||
middlewares:
|
||||
- security-chain@file
|
||||
tls: {}
|
||||
|
||||
fs1-workstation:
|
||||
rule: "Host(`fs1.workstation.internal`)"
|
||||
entrypoints:
|
||||
- websecure
|
||||
service: fs1
|
||||
tls: {}
|
||||
|
||||
services:
|
||||
fs1:
|
||||
loadBalancer:
|
||||
servers:
|
||||
- url: "http://127.0.0.1:3923" # Copyparty port example
|
||||
@@ -5,29 +5,6 @@ http:
|
||||
redirectScheme:
|
||||
scheme: https
|
||||
permanent: true
|
||||
|
||||
# Metube Basic Auth
|
||||
metube-auth:
|
||||
basicAuth:
|
||||
users:
|
||||
- "vv:$2y$05$JdT8AGUO9bd.E/PiCmKaoOJS1RFlXkrrmZ5mJ4f8/a1bEW39L3FbS"
|
||||
|
||||
realm: "MeTube Access"
|
||||
|
||||
# Basic Auth Traefik Dashboard
|
||||
auth:
|
||||
basicAuth:
|
||||
users:
|
||||
- "admin:$2y$05$.CKDD82sNUxcpaRrLbHuK.dopqt1fgurc2yfTKAT5OFzT7RvPrJHK"
|
||||
realm: "Traefik Dashboard"
|
||||
|
||||
# Basic Auth Dockmon
|
||||
dockmon-auth:
|
||||
basicAuth:
|
||||
users:
|
||||
- "admin:$2y$05$.CKDD82sNUxcpaRrLbHuK.dopqt1fgurc2yfTKAT5OFzT7RvPrJHK"
|
||||
realm: "Dockmon Access"
|
||||
|
||||
# Cloudflare IP Whitelist
|
||||
cloudflare-ipwhitelist:
|
||||
ipWhiteList:
|
||||
@@ -48,6 +25,29 @@ http:
|
||||
- "172.64.0.0/13"
|
||||
- "131.0.72.0/22"
|
||||
|
||||
# Authentik + secure headers
|
||||
security-chain:
|
||||
chain:
|
||||
middlewares:
|
||||
- authentik@file
|
||||
- security-headers@file
|
||||
authentik:
|
||||
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
|
||||
security-headers:
|
||||
headers:
|
||||
@@ -82,5 +82,5 @@ http:
|
||||
nextcloud-chain:
|
||||
chain:
|
||||
middlewares:
|
||||
- nextcloud-secure-headers
|
||||
- security-headers
|
||||
- nextcloud-secure-headers@file
|
||||
- security-headers@file
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
http:
|
||||
routers:
|
||||
acme-challenge-exempt:
|
||||
rule: "PathPrefix(`/.well-known/acme-challenge`)"
|
||||
entryPoints:
|
||||
- web
|
||||
service: noop@internal
|
||||
priority: 100
|
||||
@@ -4,7 +4,8 @@ tls:
|
||||
# Cloudflare Origin CA *.forust.xyz
|
||||
- certFile: /certs/cloudflare.pem
|
||||
keyFile: /certs/cloudflare.key
|
||||
|
||||
- certFile: /certs/xdfnx.pem
|
||||
keyFile: /certs/xdfnx.key
|
||||
stores:
|
||||
default:
|
||||
defaultCertificate:
|
||||
|
||||
+12
-13
@@ -1,34 +1,33 @@
|
||||
services:
|
||||
uptime-kuma:
|
||||
image: louislam/uptime-kuma:2
|
||||
restart: unless-stopped
|
||||
container_name: uptime-kuma
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- ./data:/app/data
|
||||
ports:
|
||||
# <Host Port>:<Container Port>
|
||||
- "3001:3001"
|
||||
- data:/app/data
|
||||
# ports:
|
||||
# - "3001:3001"
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.docker.network=traefik-proxy"
|
||||
- "traefik.docker.network=proxy"
|
||||
- "traefik.http.services.uptime-kuma.loadbalancer.server.port=3001"
|
||||
|
||||
# Prod Router
|
||||
- "traefik.http.routers.uptime-kuma.rule=Host(`uptime.forust.xyz`)"
|
||||
- "traefik.http.routers.uptime-kuma.entrypoints=websecure"
|
||||
- "traefik.http.routers.uptime-kuma.tls=true"
|
||||
- "traefik.http.services.uptime-kuma.loadbalancer.server.port=3001"
|
||||
|
||||
# Local Router
|
||||
- "traefik.http.routers.uptime-kuma-local.rule=Host(`uptime.workstation.internal`) || Host(`uptime.internal`)"
|
||||
- "traefik.http.routers.uptime-kuma-local.rule=Host(`uptime.workstation.internal`)"
|
||||
- "traefik.http.routers.uptime-kuma-local.entrypoints=websecure"
|
||||
- "traefik.http.routers.uptime-kuma-local.tls=true"
|
||||
|
||||
# Dev Router
|
||||
- "traefik.http.routers.uptime-kuma-dev.rule=Host(`uptime.gigaforust.internal`)"
|
||||
- "traefik.http.routers.uptime-kuma-dev.entrypoints=websecure"
|
||||
- "traefik.http.routers.uptime-kuma-dev.tls=true"
|
||||
networks:
|
||||
- traefik-proxy
|
||||
- proxy
|
||||
volumes:
|
||||
data:
|
||||
networks:
|
||||
traefik-proxy:
|
||||
external: true
|
||||
proxy:
|
||||
external: true
|
||||
@@ -1,9 +1,8 @@
|
||||
services:
|
||||
userbot_forust:
|
||||
forust:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile
|
||||
container_name: userbot_forust
|
||||
restart: unless-stopped
|
||||
env_file:
|
||||
- .env
|
||||
@@ -16,11 +15,10 @@ services:
|
||||
- 8.8.8.8
|
||||
- 1.1.1.1
|
||||
|
||||
userbot_anna:
|
||||
anna:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile
|
||||
container_name: userbot_anna
|
||||
restart: unless-stopped
|
||||
env_file:
|
||||
- .env
|
||||
@@ -31,27 +29,4 @@ services:
|
||||
- ./volumes/logs_anna:/app/logs
|
||||
dns:
|
||||
- 8.8.8.8
|
||||
- 1.1.1.1
|
||||
develop:
|
||||
watch:
|
||||
- action: sync
|
||||
path: modules
|
||||
target: /app/modules
|
||||
- action: sync
|
||||
path: utils
|
||||
target: /app/utils
|
||||
- action: sync
|
||||
path: main.py
|
||||
target: /app/main.py
|
||||
- action: rebuild
|
||||
path: .env
|
||||
- action: rebuild
|
||||
path: .env.anna
|
||||
|
||||
|
||||
volumes:
|
||||
downloads:
|
||||
|
||||
networks:
|
||||
userbot_network:
|
||||
driver: bridge
|
||||
- 1.1.1.1
|
||||
Reference in New Issue
Block a user