Compare commits

..

41 Commits

Author SHA1 Message Date
35c8657f13 add wal recovery guide 2026-05-21 19:12:01 +03:00
c6436d720e change to CF_DNS_API_TOKEN 2026-05-21 19:10:53 +03:00
8e38610b28 correct acme email env var 2026-05-21 19:07:12 +03:00
b1cd0e1050 add .gitignore 2026-05-14 19:45:31 +03:00
46f8b5e0a5 add .gitignore 2026-05-14 19:43:30 +03:00
ea33c80bb6 update network config 2026-05-14 19:43:20 +03:00
793e11699d add .gitignore 2026-05-14 19:43:04 +03:00
8057b502ef add .gitignore 2026-05-14 19:42:50 +03:00
994703974d add .gitignore 2026-05-14 19:42:40 +03:00
bed8333d37 update backend network 2026-05-14 19:42:30 +03:00
50eabae5ab add .gitignore 2026-05-14 19:42:18 +03:00
a2928c888f update backend network 2026-05-14 19:42:13 +03:00
dc0d3801bd add .gitignore 2026-05-14 19:41:58 +03:00
9f3339b6da update backend network 2026-05-14 19:41:50 +03:00
27d61f8ee7 add mcp network 2026-05-14 19:41:28 +03:00
be46801df6 bind traefik to mgmt network 2026-05-14 19:41:21 +03:00
65cff068d6 add .gitignore 2026-05-14 19:40:08 +03:00
f47da92f3c add .gitignore 2026-05-14 19:40:02 +03:00
c3c305ac54 update backend network 2026-05-14 19:39:48 +03:00
11ec28dfcd add .gitignore 2026-05-14 19:38:34 +03:00
adc590f346 clean secrets config 2026-05-14 19:38:05 +03:00
eea96b9f02 fix health check 2026-05-14 19:37:30 +03:00
5b0e798d37 Update backend network 2026-05-14 19:36:55 +03:00
ac8364a11a more strict rules on reading .env 2026-05-14 19:26:17 +03:00
caf2af8c60 add .gitignore 2026-05-14 19:25:32 +03:00
3065a31d08 add kimi 2026-04-21 21:44:59 +03:00
e95a2d9bbc add expose + fix traefik label 2026-04-21 21:43:36 +03:00
3e72b8d544 add expose 2026-04-21 21:42:53 +03:00
a14978c410 Add SurrealDB 2026-03-27 19:09:04 +03:00
746ebe0a59 Add AGENT.md 2026-03-22 22:24:32 +02:00
bc544a9b49 Add ttyd 2026-03-22 22:23:55 +02:00
8e50aaa5d2 Fix POSIX format + remove ssh 2026-03-22 22:21:48 +02:00
22529c4113 Add .vscode 2026-03-22 22:19:32 +02:00
32e62ee787 Fix POSIX format 2026-03-22 22:17:50 +02:00
e733ba3ae1 Removed continue extension settings 2026-03-17 21:12:00 +00:00
927beb1366 Changed docker network 2026-03-17 00:15:48 +00:00
c1db89fe6f Added it-tools-sharevb (better version) 2026-01-31 09:47:08 +00:00
26c4d2b1b7 Fixed docker secrets 2026-01-31 09:44:11 +00:00
229897a3d6 Added Super-Productivity 2026-01-30 22:10:00 +00:00
05dad9ccf7 Changed image tag to env var 2026-01-27 19:57:01 +00:00
08c79ee0eb Changed image tag to env var 2026-01-27 19:55:39 +00:00
35 changed files with 598 additions and 31 deletions

15
.gitignore vendored Normal file
View File

@@ -0,0 +1,15 @@
.secrets
.env
webapp/nginx-test
webapp/dad-domains
webapp/qbittorrent
webapp/openwebui
webapp/wisemapping
remote/rustdesk-server
remote/ttyd-ubuntu
mgmt/grafana
mgmt/prometheus
local/Y2JB-WebUI

67
.vscode/settings.json vendored Normal file
View File

@@ -0,0 +1,67 @@
{
"yaml.schemas": {
"https://raw.githubusercontent.com/compose-spec/compose-spec/master/schema/compose-spec.json": [
"**/docker-compose*.yml",
"**/docker-compose*.yaml"
],
"https://raw.githubusercontent.com/yannh/kubernetes-json-schema/master/v1.29.0/all.json": [
"**/*.k8s.yaml",
"**/*.k8s.yml",
"**/deployment*.yaml",
"**/deployment*.yml",
"**/service*.yaml",
"**/service*.yml",
"**/ingress*.yaml",
"**/ingress*.yml",
"**/configmap*.yaml",
"**/configmap*.yml",
"**/secret*.yaml",
"**/secret*.yml",
"**/pod*.yaml",
"**/pod*.yml",
"**/namespace*.yaml",
"**/namespace*.yml",
"**/replicaset*.yaml",
"**/replicaset*.yml",
"**/statefulset*.yaml",
"**/statefulset*.yml",
"**/daemonset*.yaml",
"**/daemonset*.yml",
"**/job*.yaml",
"**/job*.yml",
"**/cronjob*.yaml",
"**/cronjob*.yml",
"**/role*.yaml",
"**/role*.yml",
"**/rolebinding*.yaml",
"**/rolebinding*.yml",
"**/clusterrole*.yaml",
"**/clusterrole*.yml",
"**/clusterrolebinding*.yaml",
"**/clusterrolebinding*.yml",
"**/networkpolicy*.yaml",
"**/networkpolicy*.yml",
"**/persistentvolume*.yaml",
"**/persistentvolume*.yml",
"**/persistentvolumeclaim*.yaml",
"**/persistentvolumeclaim*.yml",
"**/storageclass*.yaml",
"**/storageclass*.yml",
"**/kustomization*.yaml",
"**/kustomization*.yml"
],
"https://json.schemastore.org/chart.json": [
"**/Chart.yaml",
"**/Chart.yml"
],
"https://json.schemastore.org/github-workflow.json": [
"**/.github/workflows/*.yml",
"**/.github/workflows/*.yaml"
]
},
"yaml.validate": true,
"yaml.format.enable": true,
"yaml.hover": true,
"yaml.completion": true,
"yaml.suggest.parentSkeletonSelectedFirst": true
}

147
AGENTS.md Normal file
View File

@@ -0,0 +1,147 @@
# Agent Guidelines for Docker Infrastructure Monorepo
## CRITICAL: Forbidden Files
**NEVER read, access, or attempt to open the following files under ANY circumstances:**
- `.env` and ALL variants (`.env.local`, `.env.development`, `.env.production`, `.env.*`)
- `.secrets/` directories at any level
- Any file in a `secrets/` directory at any level
- Credential files: `credentials.json`, `credentials.yml`, `credentials.yaml`
- Key files: `*.pem`, `*.key`, `*.p12`, `*.pfx`, `id_rsa`, `id_ecdsa`, `id_ed25519`
- Files named `token`, `tokens`, `.token`, `.tokens`, `password`, `passwords`
**What to do instead:**
- Use `.env.example` files to understand required environment variables
- Ask the user to provide values explicitly if needed
- Use placeholder values when demonstrating code
This is a hard rule. No exceptions. No "just checking". If you need env info, read the `.env.example` file or ask the user.
## Repository Structure
This is a Docker Compose monorepo for personal infrastructure hosting. The main focus is Docker services, with local tools in `local/`.
### Core Infrastructure
- `frontend/` - Cloudflare Tunnel (cloudflared/) and Traefik reverse proxy (traefik/)
- `backend/` - Core data services (postgres/, redis/)
- `mgmt/` - Management tools (portainer/, gitea/, grafana/, prometheus/, vaultwarden/, nextcloud/, authentik/)
- `webapp/` - Applications (n8n/, navidrome/, it-tools/, openwebui/, qbittorrent/, super-productivity/)
- `templates/` - Configuration templates
- `remote/` - Remote access utilities
### Local Tools
- `local/openclaw/` - WhatsApp gateway CLI (Node.js project, see its own AGENTS.md)
## Docker Commands
### Managing Services
```bash
# Start a service
cd <service-path> && docker compose up -d
# Stop a service
cd <service-path> && docker compose down
# View logs
cd <service-path> && docker compose logs -f
# Restart a service
cd <service-path> && docker compose restart
# Update/pull latest images
cd <service-path> && docker compose pull && docker compose up -d
```
### Network Architecture
- **Traefik** (frontend/traefik/) - Reverse proxy and load balancer
- **Cloudflared** (frontend/cloudflared/) - Cloudflare Tunnel for secure external access
- Services use Docker networks defined in their compose.yml files
- No port forwarding required on home router
## Service Configuration
### Environment Variables
- Copy `.env.example` to `.env` and fill in values
- Never commit `.env` files (gitignored)
- Use `.secrets/` directory for sensitive files (gitignored)
### Traefik Routing
Services exposed via Traefik use labels in compose.yml:
- `traefik.enable=true`
- `traefik.http.routers.<name>.rule=Host(`service.domain.com`)`
### Volume Mounts
- Data volumes mounted to local directories (e.g., `./data`, `./config`)
- Some services use named Docker volumes
- Backup important data directories regularly
## Working with OpenClaw (local/openclaw/)
This is a TypeScript Node.js 22+ project with its own tooling. If you need to work on it:
```bash
cd local/openclaw/
# Install and build
pnpm install
pnpm build
# Test commands
pnpm test # Run all tests
pnpm test -- src/path/file.test.ts # Run single test
pnpm test:coverage # Run with coverage
pnpm test:e2e # Run e2e tests
# Lint and format
pnpm lint
pnpm lint:fix
pnpm format
pnpm format:fix
# Pre-commit: pnpm lint && pnpm build && pnpm test
```
For full OpenClaw guidelines, see `local/openclaw/AGENTS.md`.
## Code Style Guidelines
### Docker Compose
- Use `compose.yml` (not docker-compose.yml)
- Keep services focused and minimal
- Use environment files for configuration
- Mount volumes for persistent data
### Scripts
- Shell scripts in `scripts/` directories
- Use `#!/bin/bash` or `#!/bin/sh` shebang
- Make scripts executable with `chmod +x`
### Python (local tools)
- Type hints preferred
- Use `pyproject.toml` for configuration
- Virtual environments for dependencies
### TypeScript (OpenClaw only)
- ESM modules (`"type": "module"`)
- Use `node:` prefix for Node.js built-ins
- Add `.js` extension to imports (e.g., `from "./file.js"`)
- PascalCase for types, camelCase for functions
- Run `pnpm lint` before commits
## Security Best Practices
- See **CRITICAL: Forbidden Files** section above — this is the highest priority rule in this repo
- Never commit credentials, API keys, or certificates
- Use Cloudflare Tunnel for external access (no port forwarding)
- Placeholders in documentation (e.g., `user@example.com`)
- Credentials stored outside repo in standard locations
## Git Conventions
- Conventional commit messages (e.g., `service: add health check`)
- Group related changes by service
- Don't mix unrelated service changes in one commit
- Test Docker services start correctly after changes

3
backend/postgres/.gitignore vendored Normal file
View File

@@ -0,0 +1,3 @@
.env
.secrets/
init-data.sh

View File

@@ -9,7 +9,7 @@ services:
start_period: 20s start_period: 20s
test: test:
- CMD-SHELL - CMD-SHELL
- pg_isready -U $${POSTGRES_USER_FILE} - pg_isready -U "$$(cat /run/secrets/POSTGRES_USER)"
timeout: 5s timeout: 5s
env_file: env_file:
- .env - .env
@@ -19,7 +19,7 @@ services:
volumes: volumes:
- pgdata:/var/lib/postgresql - pgdata:/var/lib/postgresql
networks: networks:
- db - backend
volumes: volumes:
pgdata: pgdata:
name: pgdata name: pgdata
@@ -29,6 +29,6 @@ secrets:
POSTGRES_PASS: POSTGRES_PASS:
file: .secrets/POSTGRES_PASS file: .secrets/POSTGRES_PASS
networks: networks:
db: backend:
external: external:
true true

View File

@@ -0,0 +1,107 @@
# PostgreSQL WAL Corruption Recovery Guide
## Symptoms
PostgreSQL container crashes on startup with logs showing:
```
LOG: unexpected pageaddr X/Y in WAL segment ...
LOG: invalid checkpoint record
PANIC: could not locate a valid checkpoint record at ...
LOG: startup process (PID N) was terminated by signal 6: Aborted
LOG: aborting startup due to startup process failure
```
The container restarts repeatedly, each time hitting the same error.
## Cause
The Write-Ahead Log (WAL) was corrupted by an unclean shutdown (power loss, host crash, force kill, etc.). PostgreSQL cannot find a valid checkpoint to resume from.
## What You Risk Losing
- **Committed data**: Safe. It is already written to the data files.
- **Uncommitted transactions** from the moment of the crash: Lost. These were only in WAL.
- **Recent changes** that were committed but not yet checkpointed: Usually safe, but there is a small risk of inconsistency.
## Recovery Procedure
### 1. Stop the Crashing Container
```bash
cd /path/to/postgres/service
docker compose down
```
### 2. Run `pg_resetwal`
This resets the WAL and forces a clean start.
**If your data is in a named Docker volume (e.g., `pgdata`):**
```bash
docker run --rm \
-v pgdata:/var/lib/postgresql \
--user postgres \
postgres:18 \
pg_resetwal -f /var/lib/postgresql/18/docker
```
> Adjust the path `/var/lib/postgresql/18/docker` to match your `PGDATA` setting.
**If your data is in a bind mount (e.g., `./data`):**
```bash
docker run --rm \
-v $(pwd)/data:/var/lib/postgresql/data \
--user postgres \
postgres:18 \
pg_resetwal -f /var/lib/postgresql/data
```
### 3. Start the Database
```bash
docker compose up -d
```
### 4. Verify
```bash
docker compose logs --tail=20
docker inspect --format='{{.State.Health.Status}}' postgres
```
You should see:
```
LOG: database system is ready to accept connections
```
And the health status should be `healthy`.
## Prevention
- Ensure graceful shutdowns: `docker compose down` instead of `docker kill`
- Use a UPS if running on bare metal to avoid power-loss crashes
- Keep backups of important data volumes
- Consider setting `restart: unless-stopped` instead of `always` to prevent rapid crash loops
## When NOT to Use This Fix
Do **not** use `pg_resetwal` if:
- You have a recent base backup and WAL archive — restore from backup instead
- You suspect data file corruption (not just WAL corruption)
- You can recover by other means (e.g., starting from a replication standby)
If unsure, copy the data directory somewhere safe before running `pg_resetwal`.
## One-Liner for Future Emergencies
If you're sure it's WAL corruption and you know your setup:
```bash
docker compose down && \
docker run --rm -v pgdata:/var/lib/postgresql --user postgres postgres:18 pg_resetwal -f /var/lib/postgresql/18/docker && \
docker compose up -d
```

View File

@@ -15,12 +15,12 @@ services:
env_file: env_file:
- .env - .env
networks: networks:
- db - backend
volumes: volumes:
- redis_data:/data - redis_data:/data
volumes: volumes:
redis_data: redis_data:
name: redis_data name: redis_data
networks: networks:
db: backend:
external: true external: true

View File

@@ -0,0 +1,4 @@
# SurrealDB Configuration
# Root password is loaded from ./.secrets/SURREAL_ROOT_PASSWORD via Docker secrets
# Timezone settings
TZ=

View File

@@ -0,0 +1,28 @@
services:
surrealdb:
image: surrealdb/surrealdb:v2
container_name: surrealdb
# entrypoint: ["/bin/sh"]
command: start --user root --pass $(cat /run/secrets/SURREAL_ROOT_PASSWORD) rocksdb:/mydata/mydatabase.db
user: root
restart: always
env_file:
- .env
secrets:
- SURREAL_ROOT_PASSWORD
volumes:
- surreal_data:/mydata
networks:
- db
volumes:
surreal_data:
name: surreal_data
secrets:
SURREAL_ROOT_PASSWORD:
file: ./.secrets/SURREAL_ROOT_PASSWORD
networks:
db:
external: true

3
frontend/cloudflared/.gitignore vendored Normal file
View File

@@ -0,0 +1,3 @@
.env
tunnel.json
config.yml

View File

@@ -8,9 +8,11 @@ services:
- traefik.enable=true - traefik.enable=true
env_file: env_file:
- .env - .env
expose:
- "7844"
networks: networks:
- frontend - frontend
networks: networks:
frontend: frontend:
external: external:
true true

View File

@@ -3,6 +3,8 @@ SUBDOMAIN=
# TRAEFIK_USER= # TRAEFIK_USER=
SSL_EMAIL_FILE=/run/secrets/CF_API_EMAIL SSL_EMAIL_FILE=/run/secrets/CF_API_EMAIL
CF_API_EMAIL_FILE=/run/secrets/CF_API_EMAIL CF_API_EMAIL_FILE=/run/secrets/CF_API_EMAIL
CF_API_KEY_FILE=/run/secrets/CF_API_KEY ACME_EMAIL=
CF_DNS_API_TOKEN_FILE=/run/secrets/CF_DNS_API_TOKEN
SSH_PORT= SSH_PORT=
TZ= TZ=
TAG=

2
frontend/traefik/.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
.env
traefik_data/

View File

@@ -1,6 +1,6 @@
services: services:
traefik: traefik:
image: "traefik:v3.5.3" image: "traefik:${TAG}"
container_name: ${SUBDOMAIN} container_name: ${SUBDOMAIN}
restart: always restart: always
command: command:
@@ -20,13 +20,12 @@ services:
- "--entrypoints.websecure.http.tls.certresolver=cloudflare" - "--entrypoints.websecure.http.tls.certresolver=cloudflare"
- "--entrypoints.websecure.http.tls.domains[0].main=${DOMAIN_NAME}" - "--entrypoints.websecure.http.tls.domains[0].main=${DOMAIN_NAME}"
- "--entrypoints.websecure.http.tls.domains[0].sans=*.${DOMAIN_NAME}" - "--entrypoints.websecure.http.tls.domains[0].sans=*.${DOMAIN_NAME}"
# - "--entrypoints.ssh.address=:${SSH_PORT}"
# Cloudflare IPs trusted for forwarded headers # Cloudflare IPs trusted for forwarded headers
- "--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.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" - "--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"
- "--certificatesresolvers.cloudflare.acme.dnschallenge=true" - "--certificatesresolvers.cloudflare.acme.dnschallenge=true"
- "--certificatesresolvers.cloudflare.acme.dnschallenge.provider=cloudflare" - "--certificatesresolvers.cloudflare.acme.dnschallenge.provider=cloudflare"
- "--certificatesresolvers.cloudflare.acme.email=${CF_API_EMAIL_FILE}" - "--certificatesresolvers.cloudflare.acme.email=${ACME_EMAIL}"
- "--certificatesresolvers.cloudflare.acme.storage=/letsencrypt/acme.json" - "--certificatesresolvers.cloudflare.acme.storage=/letsencrypt/acme.json"
labels: labels:
- traefik.enable=true - traefik.enable=true
@@ -49,12 +48,12 @@ services:
- traefik.http.middlewares.traefik_dashboard.headers.STSIncludeSubdomains=true - traefik.http.middlewares.traefik_dashboard.headers.STSIncludeSubdomains=true
- traefik.http.middlewares.traefik_dashboard.headers.STSPreload=true - traefik.http.middlewares.traefik_dashboard.headers.STSPreload=true
- traefik.http.middlewares.traefik_dashboard.headers.frameDeny=true - traefik.http.middlewares.traefik_dashboard.headers.frameDeny=true
- traefik.docker.network=mgmt
env_file: env_file:
- .env - .env
secrets: secrets:
# - SSH_PORT
- CF_API_KEY
- CF_API_EMAIL - CF_API_EMAIL
- CF_DNS_API_TOKEN
volumes: volumes:
- ./traefik_data:/letsencrypt - ./traefik_data:/letsencrypt
- /var/run/docker.sock:/var/run/docker.sock:ro - /var/run/docker.sock:/var/run/docker.sock:ro
@@ -65,14 +64,13 @@ services:
- frontend - frontend
- webapp - webapp
- mgmt - mgmt
- remote - jump
- mcp
secrets: secrets:
# SSH_PORT:
# file: .secrets/SSH_PORT
CF_API_KEY:
file: .secrets/CF_API_KEY
CF_API_EMAIL: CF_API_EMAIL:
file: .secrets/CF_API_EMAIL file: .secrets/CF_API_EMAIL
CF_DNS_API_TOKEN:
file: .secrets/CF_DNS_API_TOKEN
networks: networks:
frontend: frontend:
external: external:
@@ -83,6 +81,9 @@ networks:
mgmt: mgmt:
external: external:
true true
remote: jump:
external: external:
true true
mcp:
external:
true

3
local/adguard/.gitignore vendored Normal file
View File

@@ -0,0 +1,3 @@
.env
conf/
work/

1
mgmt/adminer/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
.env

View File

@@ -1,6 +1,6 @@
services: services:
adminer: adminer:
image: adminer:5.4.0 image: adminer:${TAG}
container_name: $SUBDOMAIN container_name: $SUBDOMAIN
restart: always restart: always
labels: labels:
@@ -25,11 +25,11 @@ services:
- .env - .env
networks: networks:
- mgmt - mgmt
- db - backend
networks: networks:
mgmt: mgmt:
external: external:
true true
db: backend:
external: external:
true true

3
mgmt/authentik/.gitignore vendored Normal file
View File

@@ -0,0 +1,3 @@
certs/
media/
custom-templates/

View File

@@ -13,7 +13,7 @@ services:
- ./custom-templates:/templates - ./custom-templates:/templates
networks: networks:
- mgmt - mgmt
- db - backend
labels: labels:
- traefik.enable=true - traefik.enable=true
- traefik.http.routers.$SUBDOMAIN.rule=Host(`${SUBDOMAIN}.${DOMAIN_NAME}`) - traefik.http.routers.$SUBDOMAIN.rule=Host(`${SUBDOMAIN}.${DOMAIN_NAME}`)
@@ -55,7 +55,7 @@ services:
- DB_PASS - DB_PASS
user: root user: root
networks: networks:
- db - backend
volumes: volumes:
# - /var/run/docker.sock:/var/run/docker.sock # Optional, only if using external outposts # - /var/run/docker.sock:/var/run/docker.sock # Optional, only if using external outposts
- ./media:/media - ./media:/media
@@ -64,7 +64,7 @@ services:
networks: networks:
mgmt: mgmt:
external: true external: true
db: backend:
external: true external: true
secrets: secrets:
SECRET_KEY: SECRET_KEY:

View File

@@ -38,14 +38,14 @@ services:
- /etc/localtime:/etc/localtime:ro - /etc/localtime:/etc/localtime:ro
networks: networks:
- mgmt - mgmt
- db - backend
volumes: volumes:
gitea-data: gitea-data:
name: gitea-data name: gitea-data
networks: networks:
mgmt: mgmt:
external: true external: true
db: backend:
external: true external: true
secrets: secrets:
DB_PASS: DB_PASS:

2
mgmt/portainer/.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
data/
.env

View File

@@ -6,7 +6,7 @@ services:
labels: labels:
- traefik.enable=true - traefik.enable=true
- traefik.http.routers.portainer.rule=Host(`${SUBDOMAIN}.${DOMAIN_NAME}`) - traefik.http.routers.portainer.rule=Host(`${SUBDOMAIN}.${DOMAIN_NAME}`)
- traefik.docker.network=webapp - traefik.docker.network=mgmt
- traefik.http.services.portainer.loadbalancer.server.port=9000 - traefik.http.services.portainer.loadbalancer.server.port=9000
- traefik.http.routers.portainer.tls=true - traefik.http.routers.portainer.tls=true
- traefik.http.routers.portainer.entrypoints=web,websecure - traefik.http.routers.portainer.entrypoints=web,websecure
@@ -25,6 +25,8 @@ services:
volumes: volumes:
- /var/run/docker.sock:/var/run/docker.sock - /var/run/docker.sock:/var/run/docker.sock
- ./data:/data - ./data:/data
expose:
- 9000
networks: networks:
- mgmt - mgmt
networks: networks:

2
mgmt/vaultwarden/.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
.env
.recovery_code

View File

@@ -0,0 +1,2 @@
# No env vars required for basic kimi CLI usage
# Add API keys or config here as needed

View File

@@ -0,0 +1,18 @@
FROM alpine:3.23
RUN apk add --no-cache bash curl
RUN addgroup -g 1000 kimi && \
adduser -D -u 1000 -G kimi kimi
USER kimi
WORKDIR /home/kimi
RUN curl -fsSL https://astral.sh/uv/install.sh | sh
RUN /home/kimi/.local/bin/uv tool install --python 3.13 kimi-cli
ENV PATH="/home/kimi/.local/bin:${PATH}"
WORKDIR /workspace
ENTRYPOINT ["kimi"]

View File

@@ -0,0 +1,12 @@
services:
kimi:
build:
context: .
network: host
image: kimi:alpine
container_name: kimi
hostname: kimi
stdin_open: true
tty: true
volumes:
- ./workspace:/workspace

6
remote/ttyd/.env.example Normal file
View File

@@ -0,0 +1,6 @@
DOMAIN_NAME=
SUBDOMAIN=
TAG=
GENERIC_TIMEZONE=
IP_ADDRESS=
TERM=xterm-256color

20
remote/ttyd/Dockerfile Normal file
View File

@@ -0,0 +1,20 @@
FROM tsl0922/ttyd:alpine
# Install ping and ssh client
RUN apk update && apk add --no-cache \
iputils \
openssh-client \
curl \
bind-tools \
bash-completion \
coreutils
RUN rm -rf /var/cache/apk/*
RUN addgroup -g 1000 ttyd && \
adduser -D -u 1000 -G ttyd tty
USER 1000:1000
# Set default command to start ttyd with bash
CMD ["ttyd", "/bin/bash"]

45
remote/ttyd/compose.yml Normal file
View File

@@ -0,0 +1,45 @@
services:
ttyd:
build:
context: .
network: host
image: ttyd:alpine
container_name: ttyd
hostname: ttyd
restart: unless-stopped
command: ["ttyd", "-W", "-o", "-u", "1000", "-g", "1000", "bash"]
stdin_open: true
tty: true
labels:
- traefik.enable=true
- traefik.http.routers.$SUBDOMAIN.rule=Host(`${SUBDOMAIN}.${DOMAIN_NAME}`)
- traefik.http.routers.$SUBDOMAIN.tls=true
- traefik.http.routers.$SUBDOMAIN.entrypoints=web,websecure
- traefik.http.routers.$SUBDOMAIN.tls.certresolver=cloudflare
- traefik.http.middlewares.$SUBDOMAIN.headers.SSLRedirect=true
- traefik.http.middlewares.$SUBDOMAIN.headers.STSSeconds=315360000
- traefik.http.middlewares.$SUBDOMAIN.headers.browserXSSFilter=true
- traefik.http.middlewares.$SUBDOMAIN.headers.contentTypeNosniff=true
- traefik.http.middlewares.$SUBDOMAIN.headers.forceSTSHeader=true
- traefik.http.middlewares.$SUBDOMAIN.headers.SSLHost=${DOMAIN_NAME}
- traefik.http.middlewares.$SUBDOMAIN.headers.STSIncludeSubdomains=true
- traefik.http.middlewares.$SUBDOMAIN.headers.STSPreload=true
- traefik.http.middlewares.$SUBDOMAIN.headers.frameDeny=true
- traefik.http.routers.$SUBDOMAIN.middlewares=authentik-forwardauth@docker
# - traefik.http.routers.$SUBDOMAIN.middlewares=$SUBDOMAIN@docker
- traefik.http.services.$SUBDOMAIN.loadbalancer.server.port=7681
- traefik.docker.network=jump
env_file:
- .env
# volumes:
networks:
jump:
lan:
ipv4_address: $IP_ADDRESS
user: "1000:1000"
# volumes:
networks:
jump:
external: true
lan:
external: true

View File

@@ -0,0 +1,2 @@
DOMAIN_NAME=
SUBDOMAIN=

View File

@@ -0,0 +1,32 @@
services:
it-tools:
image: sharevb/it-tools:latest
container_name: it-tools
healthcheck:
test: ["CMD-SHELL", "wget --no-verbose --tries=1 --spider http://127.0.0.1:8080/ || exit 1"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
labels:
- traefik.enable=true
- traefik.http.routers.$SUBDOMAIN.rule=Host(`${SUBDOMAIN}.${DOMAIN_NAME}`)
- traefik.http.routers.$SUBDOMAIN.tls=true
- traefik.http.routers.$SUBDOMAIN.entrypoints=web,websecure
- traefik.http.routers.$SUBDOMAIN.tls.certresolver=cloudflare
- traefik.http.middlewares.$SUBDOMAIN.headers.SSLRedirect=true
- traefik.http.middlewares.$SUBDOMAIN.headers.STSSeconds=315360000
- traefik.http.middlewares.$SUBDOMAIN.headers.browserXSSFilter=true
- traefik.http.middlewares.$SUBDOMAIN.headers.contentTypeNosniff=true
- traefik.http.middlewares.$SUBDOMAIN.headers.forceSTSHeader=true
- traefik.http.middlewares.$SUBDOMAIN.headers.SSLHost=${DOMAIN_NAME}
- traefik.http.middlewares.$SUBDOMAIN.headers.STSIncludeSubdomains=true
- traefik.http.middlewares.$SUBDOMAIN.headers.STSPreload=true
- traefik.http.routers.$SUBDOMAIN.middlewares=$SUBDOMAIN@docker
- traefik.http.services.$SUBDOMAIN.loadbalancer.server.port=8080
networks:
- webapp
networks:
webapp:
external:
true

2
webapp/n8n/.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
.env
local-files

View File

@@ -30,7 +30,8 @@ services:
- ./local-files:/files - ./local-files:/files
networks: networks:
- webapp - webapp
- db - backend
- mcp
secrets: secrets:
DB_PASS: DB_PASS:
file: .secrets/DB_PASS file: .secrets/DB_PASS
@@ -38,7 +39,10 @@ networks:
webapp: webapp:
external: external:
true true
db: backend:
external:
true
mcp:
external: external:
true true
volumes: volumes:

3
webapp/navidrome/.gitignore vendored Normal file
View File

@@ -0,0 +1,3 @@
data/
music/
music

View File

@@ -0,0 +1,27 @@
services:
super-productivity:
image: johannesjo/super-productivity:latest
container_name: super-productivity
labels:
- traefik.enable=true
- traefik.http.routers.$SUBDOMAIN.rule=Host(`${SUBDOMAIN}.${DOMAIN_NAME}`)
- traefik.http.routers.$SUBDOMAIN.tls=true
- traefik.http.routers.$SUBDOMAIN.entrypoints=web,websecure
- traefik.http.routers.$SUBDOMAIN.tls.certresolver=cloudflare
- traefik.http.middlewares.$SUBDOMAIN.headers.SSLRedirect=true
- traefik.http.middlewares.$SUBDOMAIN.headers.STSSeconds=315360000
- traefik.http.middlewares.$SUBDOMAIN.headers.browserXSSFilter=true
- traefik.http.middlewares.$SUBDOMAIN.headers.contentTypeNosniff=true
- traefik.http.middlewares.$SUBDOMAIN.headers.forceSTSHeader=true
- traefik.http.middlewares.$SUBDOMAIN.headers.SSLHost=${DOMAIN_NAME}
- traefik.http.middlewares.$SUBDOMAIN.headers.STSIncludeSubdomains=true
- traefik.http.middlewares.$SUBDOMAIN.headers.STSPreload=true
- traefik.http.routers.$SUBDOMAIN.middlewares=authentik-forwardauth@docker
- traefik.http.services.$SUBDOMAIN.loadbalancer.server.port=80
restart: unless-stopped
networks:
- webapp
networks:
webapp:
external:
true