Compare commits
33 Commits
f4b46d2926
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a0271a88ef | ||
|
|
e92389a44a | ||
|
|
40b0d23f57 | ||
|
|
5a20b9809c | ||
|
|
bbfc5843d8 | ||
|
|
39c368ebd5 | ||
|
|
98ea915ce8 | ||
|
|
dfa81b3396 | ||
|
|
5938bd3cdd | ||
|
|
3050f28460 | ||
|
|
51187de49a | ||
|
|
fad38a229f | ||
|
|
72a9f0ae54 | ||
|
|
bdac46a6c0 | ||
|
|
82bf22006d | ||
|
|
45235aafe5 | ||
|
|
6fc47a50a2 | ||
|
|
3e9fa63083 | ||
|
|
cc3ab19e53 | ||
|
|
96ccb78c5c | ||
|
|
72c0a68836 | ||
|
|
fae1e7f227 | ||
|
|
f474ea3484 | ||
|
|
2279f8cf4b | ||
|
|
10b98f1dba | ||
|
|
60c5158267 | ||
|
|
f6f110d964 | ||
|
|
ff9934a0c7 | ||
|
|
f76a07ea8b | ||
|
|
35c19dcd49 | ||
|
|
20feed2b30 | ||
|
|
c353bb1c78 | ||
|
|
f50667712d |
5
.gitignore
vendored
5
.gitignore
vendored
@@ -1,4 +1,5 @@
|
||||
traefik/dynamic.yml
|
||||
traefik/static.yml
|
||||
core/dynamic.yml
|
||||
core/static.yml
|
||||
crowdsec/acquis.yaml
|
||||
traefik/acquis.yaml
|
||||
core/acquis.yaml
|
||||
686
README.md
Normal file
686
README.md
Normal file
@@ -0,0 +1,686 @@
|
||||
# Docker Swarm Cluster Report
|
||||
|
||||
**Generated**: 2025-11-29 17:13:31 UTC
|
||||
|
||||
## Swarm Cluster Overview
|
||||
|
||||
### Node Status
|
||||
|
||||
| p0-compute | Ready | Active | Reachable | 29.0.4 |
|
||||
| p1-control | Ready | Active | Reachable | 29.0.4 |
|
||||
| p2-control | Ready | Active | Reachable | 29.0.4 |
|
||||
| p3-control | Ready | Active | Leader | 29.0.4 |
|
||||
| p4-compute | Ready | Active | Reachable | 29.0.4 |
|
||||
| p5-compute | Ready | Active | Reachable | 29.0.4 |
|
||||
|
||||
**Cluster Details**:
|
||||
- Cluster ID: iutii5nymo40dsgcuxnfdh6jr
|
||||
- Created: 2025-11-13 14:34:48.038680238 +0000 UTC
|
||||
- Total Nodes: 6
|
||||
- Manager Nodes: 6
|
||||
- Engine Version: 29.0.4
|
||||
- Operating System: Ubuntu 24.04.3 LTS
|
||||
- Kernel: 6.8.0-88-generic
|
||||
|
||||
---
|
||||
|
||||
## Hardware Details
|
||||
|
||||
### p0-compute (Current Node)
|
||||
|
||||
**Processor**:
|
||||
```
|
||||
Architecture: x86_64
|
||||
CPU(s): 16
|
||||
On-line CPU(s) list: 0-15
|
||||
Model name: AMD Ryzen 7 5800H with Radeon Graphics
|
||||
Thread(s) per core: 2
|
||||
Core(s) per socket: 8
|
||||
Socket(s): 1
|
||||
CPU(s) scaling MHz: 83%
|
||||
CPU max MHz: 4463.0000
|
||||
CPU min MHz: 400.0000
|
||||
NUMA node0 CPU(s): 0-15
|
||||
```
|
||||
|
||||
**Memory**:
|
||||
```
|
||||
total used free shared buff/cache available
|
||||
Mem: 28Gi 2.2Gi 7.7Gi 2.4Mi 18Gi 26Gi
|
||||
Swap: 8.0Gi 0B 8.0Gi
|
||||
```
|
||||
|
||||
**Storage**:
|
||||
```
|
||||
Filesystem Size Used Avail Use% Mounted on
|
||||
/dev/mapper/ubuntu--vg-ubuntu--lv 98G 39G 55G 42% /
|
||||
/dev/nvme0n1p2 2.0G 198M 1.6G 11% /boot
|
||||
/dev/nvme0n1p1 1.1G 6.2M 1.1G 1% /boot/efi
|
||||
```
|
||||
|
||||
**Block Devices**:
|
||||
```
|
||||
NAME SIZE TYPE MOUNTPOINT FSTYPE
|
||||
nvme0n1 953.9G disk
|
||||
├─nvme0n1p1 1G part /boot/efi vfat
|
||||
├─nvme0n1p2 2G part /boot ext4
|
||||
└─nvme0n1p3 950.8G part LVM2_member
|
||||
└─ubuntu--vg-ubuntu--lv 100G lvm / ext4
|
||||
```
|
||||
|
||||
**Network Interfaces**:
|
||||
```
|
||||
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
|
||||
inet 127.0.0.1/8 scope host lo
|
||||
2: enp1s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
|
||||
inet 10.0.4.11/24 metric 100 brd 10.0.4.255 scope global dynamic enp1s0
|
||||
3: wlo1: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN group default qlen 1000
|
||||
4: docker_gwbridge: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
|
||||
inet 172.18.0.1/16 brd 172.18.255.255 scope global docker_gwbridge
|
||||
5: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
|
||||
inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
|
||||
106: vethb68b357@if105: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker_gwbridge state UP group default
|
||||
211: veth281d180@if210: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker_gwbridge state UP group default
|
||||
215: veth07de1c1@if214: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker_gwbridge state UP group default
|
||||
219: vethbb8c162@if218: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker_gwbridge state UP group default
|
||||
225: veth26a4063@if224: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker_gwbridge state UP group default
|
||||
231: veth7d33e67@if230: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker_gwbridge state UP group default
|
||||
237: veth5e29c61@if236: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker_gwbridge state UP group default
|
||||
```
|
||||
|
||||
**System Load**:
|
||||
```
|
||||
17:13:31 up 8 days, 4:59, 3 users, load average: 0.30, 0.16, 0.19
|
||||
Load: 0.30 0.16 0.19 1/849 3444576
|
||||
```
|
||||
|
||||
### Remote Nodes
|
||||
|
||||
#### p1-control (10.0.4.12)
|
||||
|
||||
**CPU**: `Cortex-A76`
|
||||
**Cores**: `4`
|
||||
**Memory**: `N/A`
|
||||
**Storage**: `235G total, 8.9G used, 216G available (4% used)`
|
||||
**Uptime**: `up 1 week, 1 day, 4 hours, 58 minutes`
|
||||
|
||||
#### p2-control (10.0.4.13)
|
||||
|
||||
**CPU**: `Cortex-A76`
|
||||
**Cores**: `4`
|
||||
**Memory**: `N/A`
|
||||
**Storage**: `117G total, 7.3G used, 105G available (7% used)`
|
||||
**Uptime**: `up 1 week, 1 day, 4 hours, 56 minutes`
|
||||
|
||||
#### p3-control (10.0.4.14)
|
||||
|
||||
**CPU**: `Cortex-A76`
|
||||
**Cores**: `4`
|
||||
**Memory**: `N/A`
|
||||
**Storage**: `470G total, 6.9G used, 444G available (2% used)`
|
||||
**Uptime**: `up 1 week, 1 day, 4 hours, 55 minutes`
|
||||
|
||||
#### p4-compute (10.0.4.15)
|
||||
|
||||
**CPU**: `12th Gen Intel(R) Core(TM) i5-12600K`
|
||||
**Cores**: `5`
|
||||
**Memory**: `N/A`
|
||||
**Storage**: `60G total, 22G used, 36G available (38% used)`
|
||||
**Uptime**: `up 28 minutes`
|
||||
|
||||
#### p5-compute (10.0.4.16)
|
||||
|
||||
**CPU**: `12th Gen Intel(R) Core(TM) i5-12600K`
|
||||
**Cores**: `5`
|
||||
**Memory**: `N/A`
|
||||
**Storage**: `60G total, 20G used, 38G available (34% used)`
|
||||
**Uptime**: `up 28 minutes`
|
||||
|
||||
---
|
||||
|
||||
## Storage Infrastructure
|
||||
|
||||
### Mounted Filesystems
|
||||
```
|
||||
Filesystem Size Used Avail Use% Mounted on
|
||||
10.0.4.10:/mnt/user/frostlabs 4.6T 815G 3.8T 18% /home/doc/projects/homelab
|
||||
```
|
||||
|
||||
### GlusterFS Shared Storage
|
||||
```
|
||||
localhost:swarm-data on /home/doc/projects/swarm-data type fuse.glusterfs (rw,relatime,user_id=0,group_id=0,default_permissions,allow_other,max_read=131072,_netdev)
|
||||
```
|
||||
|
||||
**Application Data Usage**:
|
||||
```
|
||||
1.3G /home/doc/projects/swarm-data/n8n
|
||||
815M /home/doc/projects/swarm-data/paperless
|
||||
65M /home/doc/projects/swarm-data/crowdsec
|
||||
26M /home/doc/projects/swarm-data/traefik
|
||||
13M /home/doc/projects/swarm-data/leantime
|
||||
873K /home/doc/projects/swarm-data/portainer
|
||||
295K /home/doc/projects/swarm-data/webfiles
|
||||
148K /home/doc/projects/swarm-data/authentik
|
||||
101K /home/doc/projects/swarm-data/cluster-reports
|
||||
25K /home/doc/projects/swarm-data/peertube
|
||||
23K /home/doc/projects/swarm-data/pulse
|
||||
14K /home/doc/projects/swarm-data/webservers
|
||||
12K /home/doc/projects/swarm-data/wiki
|
||||
11K /home/doc/projects/swarm-data/swarm-cluster-report.md
|
||||
8.0K /home/doc/projects/swarm-data/outline
|
||||
```
|
||||
|
||||
### Docker Storage
|
||||
```
|
||||
TYPE TOTAL ACTIVE SIZE RECLAIMABLE
|
||||
Images 14 6 9.906GB 3.897GB (39%)
|
||||
Containers 6 6 76.17MB 0B (0%)
|
||||
Local Volumes 6 4 859.7MB 219B (0%)
|
||||
Build Cache 43 0 2.718GB 2.718GB
|
||||
```
|
||||
|
||||
### Docker Volumes
|
||||
```
|
||||
DRIVER VOLUME NAME
|
||||
local 2a12ce4d80ed228df0407922ec7e7ab4ec377a5bf1ba705c66af91c55b2a5fe9
|
||||
local 253ac8ad683409f2b8c98984020595bc40e44f39cc2be9dda83c52b3948a5288
|
||||
local e8b304d313cf8e6d5f916b407e3136eb8dce42113185395c0d4bdac187c54420
|
||||
local netdata_netdatacache
|
||||
local netdata_netdataconfig
|
||||
local netdata_netdatalib
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Networking
|
||||
|
||||
### Docker Networks
|
||||
```
|
||||
NETWORK ID NAME DRIVER SCOPE
|
||||
96516fc92029 bridge bridge local
|
||||
108989d65846 docker_gwbridge bridge local
|
||||
uqtj8gddx10e frostlabs overlay swarm
|
||||
91db06c956a7 host host local
|
||||
wkdnemyo9t0m ingress overlay swarm
|
||||
d3024e25ac24 none null local
|
||||
```
|
||||
|
||||
### Overlay Network Details (frostlabs)
|
||||
```json
|
||||
{
|
||||
"Name": "frostlabs",
|
||||
"Id": "uqtj8gddx10e5t4qdea05tt2c",
|
||||
"Created": "2025-11-29T17:04:44.054714019Z",
|
||||
"Scope": "swarm",
|
||||
"Driver": "overlay",
|
||||
"EnableIPv4": true,
|
||||
"EnableIPv6": false,
|
||||
"IPAM": {
|
||||
"Driver": "default",
|
||||
"Options": null,
|
||||
"Config": [
|
||||
{
|
||||
"Subnet": "10.0.1.0/24",
|
||||
"IPRange": "",
|
||||
"Gateway": "10.0.1.1"
|
||||
}
|
||||
]
|
||||
},
|
||||
"Internal": false,
|
||||
"Attachable": true,
|
||||
"Ingress": false,
|
||||
"ConfigFrom": {
|
||||
"Network": ""
|
||||
},
|
||||
"ConfigOnly": false,
|
||||
"Options": {
|
||||
"com.docker.network.driver.overlay.vxlanid_list": "4097"
|
||||
},
|
||||
"Labels": {},
|
||||
"Peers": [
|
||||
{
|
||||
"Name": "4d3d131a9072",
|
||||
"IP": "10.0.4.12"
|
||||
},
|
||||
{
|
||||
"Name": "2dc3e26647be",
|
||||
"IP": "10.0.4.16"
|
||||
},
|
||||
{
|
||||
"Name": "0fa05fb4badc",
|
||||
"IP": "10.0.4.14"
|
||||
},
|
||||
{
|
||||
"Name": "ba45d88141ad",
|
||||
"IP": "10.0.4.13"
|
||||
},
|
||||
{
|
||||
"Name": "d5e101a6aa8a",
|
||||
"IP": "10.0.4.11"
|
||||
},
|
||||
{
|
||||
"Name": "532747b2bb73",
|
||||
"IP": "10.0.4.15"
|
||||
}
|
||||
],
|
||||
"Containers": {
|
||||
"387433afd0a4949b3f19ca2de1d397cfe7e8ddcd784686e72cbefd8fa8aeb70e": {
|
||||
"Name": "netdata_netdata.vtgnge0wpukgwn3ct2c3ue81g.2uap80qv8lbrs5atilc2u3qia",
|
||||
"EndpointID": "cc36398dc0cf6273ba8b4743dacfe0d517d4dc8b76d60af1fba6186e2d7f4549",
|
||||
"MacAddress": "02:42:0a:00:01:75",
|
||||
"IPv4Address": "10.0.1.117/24",
|
||||
"IPv6Address": ""
|
||||
},
|
||||
"422044b5c056c63c580fc795e8519c603c8045562a14d9646d03274fd0acf324": {
|
||||
"Name": "core_agent.vtgnge0wpukgwn3ct2c3ue81g.3ftzdym5g2cej9i3rineisqs7",
|
||||
"EndpointID": "3c3bc64b2285a70a4587499c211c89333d816635232b571baee68314881c9d14",
|
||||
"MacAddress": "02:42:0a:00:01:5c",
|
||||
"IPv4Address": "10.0.1.92/24",
|
||||
"IPv6Address": ""
|
||||
},
|
||||
"65b52609f5a5b103f1ec3412de4afbcfb7dfe54a9705f6120b3d931ce5fe1aae": {
|
||||
"Name": "n8n_n8n.1.kv9s1hom7fk7olv4smstk7n43",
|
||||
"EndpointID": "686d537fe00c8f733eb41169fafb0ce560e3ac5df25031ad6302a0c12115e523",
|
||||
"MacAddress": "02:42:0a:00:01:6e",
|
||||
"IPv4Address": "10.0.1.110/24",
|
||||
"IPv6Address": ""
|
||||
},
|
||||
"7787e194dd2f76696d6858cceb4007bc4ab16e78b181f7a109388a23a92906d5": {
|
||||
"Name": "core_redis.1.j1qqhrwydjyrlpxyhrjryfmhi",
|
||||
"EndpointID": "7db1e8881a7ade0b3d3b9a751404b7358a6833c8c0b58b5929ff1b8cdfb7f9d9",
|
||||
"MacAddress": "02:42:0a:00:01:63",
|
||||
"IPv4Address": "10.0.1.99/24",
|
||||
"IPv6Address": ""
|
||||
},
|
||||
"9ff8ccaa9e50caeafa27c2404aefe9306ac3ca65177d33c8100e453bb6eeaac2": {
|
||||
"Name": "dozzle_dozzle.vtgnge0wpukgwn3ct2c3ue81g.xylxcjit84hequnjrbxbt5088",
|
||||
"EndpointID": "bd7250dc9c019897f468d46569b7206a34e0004f3f58e1382b35637e6d18cee6",
|
||||
"MacAddress": "02:42:0a:00:01:6c",
|
||||
"IPv4Address": "10.0.1.108/24",
|
||||
"IPv6Address": ""
|
||||
},
|
||||
"d773d035f9402422f6f1d0fd37a14d9f741d32576a59c52337fd5dfa5914871d": {
|
||||
"Name": "peertube_peertube.1.xkkvqxwhryep4enozc0zsfbf1",
|
||||
"EndpointID": "420575b413b02b6ecaf3e8c46fdb9cab0dbadb16b053c97011497f9f5f96a4e2",
|
||||
"MacAddress": "02:42:0a:00:01:7f",
|
||||
"IPv4Address": "10.0.1.127/24",
|
||||
"IPv6Address": ""
|
||||
},
|
||||
"lb-frostlabs": {
|
||||
"Name": "frostlabs-endpoint",
|
||||
"EndpointID": "0a1eb5fb6b06df20ff9f0cbc75a04936a0028441138579bab0f1401730559377",
|
||||
"MacAddress": "02:42:0a:00:01:60",
|
||||
"IPv4Address": "10.0.1.96/24",
|
||||
"IPv6Address": ""
|
||||
}
|
||||
},
|
||||
"Status": {
|
||||
"IPAM": {
|
||||
"Subnets": {
|
||||
"10.0.1.0/24": {
|
||||
"IPsInUse": 58,
|
||||
"DynamicIPsAvailable": 198
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Published Ports
|
||||
```
|
||||
adminer_adminer:
|
||||
core_agent:
|
||||
core_authentik_server:
|
||||
core_authentik_worker:
|
||||
core_portainer: *:9000->9000/tcp
|
||||
core_redis:
|
||||
core_traefik: *:80->80/tcp, *:443->443/tcp, *:8082->8080/tcp
|
||||
dozzle_dozzle: *:8080->8080/tcp
|
||||
n8n_n8n: *:5678->5678/tcp
|
||||
netdata_netdata: *:19999->19999/tcp
|
||||
paperless_paperless_redis:
|
||||
paperless_paperless_webserver:
|
||||
peertube_peertube:
|
||||
peertube_postgres: *:5432->5432/tcp
|
||||
peertube_redis:
|
||||
tracker_tracker-nginx: *:8180->80/tcp
|
||||
wiki_wiki: *:3000->3000/tcp
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Deployed Services
|
||||
|
||||
### Stacks
|
||||
```
|
||||
NAME SERVICES
|
||||
adminer 1
|
||||
core 6
|
||||
dozzle 1
|
||||
n8n 1
|
||||
netdata 1
|
||||
paperless 2
|
||||
peertube 3
|
||||
tracker 1
|
||||
wiki 1
|
||||
```
|
||||
|
||||
### Services
|
||||
```
|
||||
ID NAME MODE REPLICAS IMAGE PORTS
|
||||
m9omofpn9bw6 adminer_adminer replicated 1/1 adminer:latest
|
||||
sj19vr2nw0kp core_agent global 6/6 portainer/agent:latest
|
||||
5k4qkbgfeys8 core_authentik_server replicated 1/1 ghcr.io/goauthentik/server:2025.10.0
|
||||
65qy6wmjbdsn core_authentik_worker replicated 1/1 ghcr.io/goauthentik/server:2025.10.0
|
||||
xng4hh1x7spf core_portainer replicated 1/1 portainer/portainer-ce:latest *:9000->9000/tcp
|
||||
cd0cvtzw8j0t core_redis replicated 1/1 redis:alpine
|
||||
rjsk8v0lebc0 core_traefik replicated 1/1 traefik:v3.6.1 *:80->80/tcp, *:443->443/tcp, *:8082->8080/tcp
|
||||
i6mu3tf3u5ef dozzle_dozzle global 6/6 amir20/dozzle:latest *:8080->8080/tcp
|
||||
pp0cz85w2kdi n8n_n8n replicated 1/1 n8nio/n8n:latest *:5678->5678/tcp
|
||||
kpe5e0aez8j0 netdata_netdata global 6/6 netdata/netdata:stable *:19999->19999/tcp
|
||||
imy76qvd40hq paperless_paperless_redis replicated 1/1 redis:alpine
|
||||
eqf52b9sgmcf paperless_paperless_webserver replicated 1/1 ghcr.io/paperless-ngx/paperless-ngx:latest
|
||||
ysy9weeo8n41 peertube_peertube replicated 1/1 chocobozzz/peertube:production-bookworm
|
||||
uyo4qxsa8r4v peertube_postgres replicated 1/1 postgres:17-alpine *:5432->5432/tcp
|
||||
703wunzrgu99 peertube_redis replicated 1/1 redis:7-alpine
|
||||
p32115n71f0s tracker_tracker-nginx replicated 1/1 nginx:alpine *:8180->80/tcp
|
||||
sujusu1pzal8 wiki_wiki replicated 1/1 ghcr.io/requarks/wiki:2 *:3000->3000/tcp
|
||||
```
|
||||
|
||||
### Service Distribution by Stack
|
||||
|
||||
#### Stack: adminer
|
||||
```
|
||||
adminer_adminer.1 p4-compute Running 7 minutes ago
|
||||
```
|
||||
|
||||
#### Stack: core
|
||||
```
|
||||
core_agent.5lfnhogleddgqenj9pb3bnbiq p5-compute Running 8 minutes ago
|
||||
core_agent.9k5wdjeo2pn6bgm6t3kni105w p4-compute Running 8 minutes ago
|
||||
core_agent.lmqjm4tqh1dw12rn49b5zmsv7 p1-control Running 8 minutes ago
|
||||
core_agent.v9u4wpdzqvjsw1d7v2nqnudjv p2-control Running 8 minutes ago
|
||||
core_agent.vbd9ze987kd06kb6oorfziuga p3-control Running 8 minutes ago
|
||||
core_agent.vtgnge0wpukgwn3ct2c3ue81g p0-compute Running 8 minutes ago
|
||||
core_authentik_server.1 p1-control Running 8 minutes ago
|
||||
core_authentik_worker.1 p5-compute Running 8 minutes ago
|
||||
core_portainer.1 p2-control Running 8 minutes ago
|
||||
core_redis.1 p0-compute Running 8 minutes ago
|
||||
core_traefik.1 p3-control Running 8 minutes ago
|
||||
```
|
||||
|
||||
#### Stack: dozzle
|
||||
```
|
||||
dozzle_dozzle.5lfnhogleddgqenj9pb3bnbiq p5-compute Running 7 minutes ago
|
||||
dozzle_dozzle.9k5wdjeo2pn6bgm6t3kni105w p4-compute Running 7 minutes ago
|
||||
dozzle_dozzle.lmqjm4tqh1dw12rn49b5zmsv7 p1-control Running 7 minutes ago
|
||||
dozzle_dozzle.v9u4wpdzqvjsw1d7v2nqnudjv p2-control Running 7 minutes ago
|
||||
dozzle_dozzle.vbd9ze987kd06kb6oorfziuga p3-control Running 7 minutes ago
|
||||
dozzle_dozzle.vtgnge0wpukgwn3ct2c3ue81g p0-compute Running 7 minutes ago
|
||||
```
|
||||
|
||||
#### Stack: n8n
|
||||
```
|
||||
n8n_n8n.1 p0-compute Running 6 minutes ago
|
||||
```
|
||||
|
||||
#### Stack: netdata
|
||||
```
|
||||
netdata_netdata.5lfnhogleddgqenj9pb3bnbiq p5-compute Running 6 minutes ago
|
||||
netdata_netdata.9k5wdjeo2pn6bgm6t3kni105w p4-compute Running 6 minutes ago
|
||||
netdata_netdata.lmqjm4tqh1dw12rn49b5zmsv7 p1-control Running 6 minutes ago
|
||||
netdata_netdata.v9u4wpdzqvjsw1d7v2nqnudjv p2-control Running 6 minutes ago
|
||||
netdata_netdata.vbd9ze987kd06kb6oorfziuga p3-control Running 6 minutes ago
|
||||
netdata_netdata.vtgnge0wpukgwn3ct2c3ue81g p0-compute Running 6 minutes ago
|
||||
```
|
||||
|
||||
#### Stack: paperless
|
||||
```
|
||||
paperless_paperless_redis.1 p5-compute Running 6 minutes ago
|
||||
paperless_paperless_webserver.1 p4-compute Running 6 minutes ago
|
||||
```
|
||||
|
||||
#### Stack: peertube
|
||||
```
|
||||
peertube_peertube.1 p0-compute Running 6 minutes ago
|
||||
peertube_postgres.1 p2-control Running 6 minutes ago
|
||||
peertube_redis.1 p1-control Running 6 minutes ago
|
||||
```
|
||||
|
||||
#### Stack: tracker
|
||||
```
|
||||
tracker_tracker-nginx.1 p5-compute Running 6 minutes ago
|
||||
```
|
||||
|
||||
#### Stack: wiki
|
||||
```
|
||||
wiki_wiki.1 p4-compute Running 6 minutes ago
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Container Distribution
|
||||
|
||||
### Current Node Containers
|
||||
```
|
||||
NAMES IMAGE STATUS
|
||||
peertube_peertube.1.xkkvqxwhryep4enozc0zsfbf1 chocobozzz/peertube:production-bookworm Up 6 minutes
|
||||
n8n_n8n.1.kv9s1hom7fk7olv4smstk7n43 n8nio/n8n:latest Up 6 minutes (healthy)
|
||||
netdata_netdata.vtgnge0wpukgwn3ct2c3ue81g.2uap80qv8lbrs5atilc2u3qia netdata/netdata:stable Up 7 minutes (healthy)
|
||||
dozzle_dozzle.vtgnge0wpukgwn3ct2c3ue81g.xylxcjit84hequnjrbxbt5088 amir20/dozzle:latest Up 7 minutes
|
||||
core_redis.1.j1qqhrwydjyrlpxyhrjryfmhi redis:alpine Up 8 minutes (healthy)
|
||||
core_agent.vtgnge0wpukgwn3ct2c3ue81g.3ftzdym5g2cej9i3rineisqs7 portainer/agent:latest Up 8 minutes
|
||||
```
|
||||
|
||||
### All Nodes Container Count
|
||||
- p0-compute: 6 containers
|
||||
- p1-control: 5 containers
|
||||
- p2-control: 5 containers
|
||||
- p3-control: 4 containers
|
||||
- p4-compute: 6 containers
|
||||
- p5-compute: 6 containers
|
||||
|
||||
---
|
||||
|
||||
## Node Labels & Roles
|
||||
|
||||
```
|
||||
p0-compute: map[task:compute]
|
||||
p1-control: map[task:control]
|
||||
p2-control: map[task:control]
|
||||
p3-control: map[task:control]
|
||||
p4-compute: map[task:compute]
|
||||
p5-compute: map[task:compute]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Cluster Configuration
|
||||
|
||||
```json
|
||||
{
|
||||
"NodeID": "vtgnge0wpukgwn3ct2c3ue81g",
|
||||
"NodeAddr": "10.0.4.11",
|
||||
"LocalNodeState": "active",
|
||||
"ControlAvailable": true,
|
||||
"Error": "",
|
||||
"RemoteManagers": [
|
||||
{
|
||||
"NodeID": "vbd9ze987kd06kb6oorfziuga",
|
||||
"Addr": "10.0.4.14:2377"
|
||||
},
|
||||
{
|
||||
"NodeID": "vtgnge0wpukgwn3ct2c3ue81g",
|
||||
"Addr": "10.0.4.11:2377"
|
||||
},
|
||||
{
|
||||
"NodeID": "5lfnhogleddgqenj9pb3bnbiq",
|
||||
"Addr": "10.0.4.16:2377"
|
||||
},
|
||||
{
|
||||
"NodeID": "9k5wdjeo2pn6bgm6t3kni105w",
|
||||
"Addr": "10.0.4.15:2377"
|
||||
},
|
||||
{
|
||||
"NodeID": "lmqjm4tqh1dw12rn49b5zmsv7",
|
||||
"Addr": "10.0.4.12:2377"
|
||||
},
|
||||
{
|
||||
"NodeID": "v9u4wpdzqvjsw1d7v2nqnudjv",
|
||||
"Addr": "10.0.4.13:2377"
|
||||
}
|
||||
],
|
||||
"Nodes": 6,
|
||||
"Managers": 6,
|
||||
"Cluster": {
|
||||
"ID": "iutii5nymo40dsgcuxnfdh6jr",
|
||||
"Version": {
|
||||
"Index": 135075
|
||||
},
|
||||
"CreatedAt": "2025-11-13T14:34:48.038680238Z",
|
||||
"UpdatedAt": "2025-11-29T10:25:03.236675911Z",
|
||||
"Spec": {
|
||||
"Name": "default",
|
||||
"Labels": {},
|
||||
"Orchestration": {
|
||||
"TaskHistoryRetentionLimit": 5
|
||||
},
|
||||
"Raft": {
|
||||
"SnapshotInterval": 10000,
|
||||
"KeepOldSnapshots": 0,
|
||||
"LogEntriesForSlowFollowers": 500,
|
||||
"ElectionTick": 10,
|
||||
"HeartbeatTick": 1
|
||||
},
|
||||
"Dispatcher": {
|
||||
"HeartbeatPeriod": 5000000000
|
||||
},
|
||||
"CAConfig": {
|
||||
"NodeCertExpiry": 7776000000000000
|
||||
},
|
||||
"TaskDefaults": {},
|
||||
"EncryptionConfig": {
|
||||
"AutoLockManagers": false
|
||||
}
|
||||
},
|
||||
"TLSInfo": {
|
||||
"TrustRoot": "-----BEGIN CERTIFICATE-----\nMIIBajCCARCgAwIBAgIUOkVEhR7ir7HWSBC4Eoj71XBnCUgwCgYIKoZIzj0EAwIw\nEzERMA8GA1UEAxMIc3dhcm0tY2EwHhcNMjUxMTEzMTQzMDAwWhcNNDUxMTA4MTQz\nMDAwWjATMREwDwYDVQQDEwhzd2FybS1jYTBZMBMGByqGSM49AgEGCCqGSM49AwEH\nA0IABPqdHvAk/XP51IaMZE8GWt2h90o8JsKoo1O8VS6Qs4yJ0N0HZ0vHmiIm9T3i\nkJ6Vhj6IfSBNBReFe3MVX3i4FvejQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMB\nAf8EBTADAQH/MB0GA1UdDgQWBBSzhamb4jVwspS8Ceflk62jvU9AwDAKBggqhkjO\nPQQDAgNIADBFAiEAnduA5iS0SMX/jllJv8Y/XNgVoDcOTXs5gntn5uZOhwYCIEGD\nEsN73RfTYcLhmknpiMiiDnqAY6infpMC27w66iNz\n-----END CERTIFICATE-----\n",
|
||||
"CertIssuerSubject": "MBMxETAPBgNVBAMTCHN3YXJtLWNh",
|
||||
"CertIssuerPublicKey": "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE+p0e8CT9c/nUhoxkTwZa3aH3SjwmwqijU7xVLpCzjInQ3QdnS8eaIib1PeKQnpWGPoh9IE0FF4V7cxVfeLgW9w=="
|
||||
},
|
||||
"RootRotationInProgress": false,
|
||||
"DefaultAddrPool": [
|
||||
"10.0.0.0/8"
|
||||
],
|
||||
"SubnetSize": 24,
|
||||
"DataPathPort": 4789
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## System Health
|
||||
|
||||
### Service Health Status
|
||||
```
|
||||
adminer_adminer 1/1
|
||||
core_agent 6/6
|
||||
core_authentik_server 1/1
|
||||
core_authentik_worker 1/1
|
||||
core_portainer 1/1
|
||||
core_redis 1/1
|
||||
core_traefik 1/1
|
||||
dozzle_dozzle 6/6
|
||||
n8n_n8n 1/1
|
||||
netdata_netdata 6/6
|
||||
paperless_paperless_redis 1/1
|
||||
paperless_paperless_webserver 1/1
|
||||
peertube_peertube 1/1
|
||||
peertube_postgres 1/1
|
||||
peertube_redis 1/1
|
||||
tracker_tracker-nginx 1/1
|
||||
wiki_wiki 1/1
|
||||
```
|
||||
|
||||
### Node Availability
|
||||
```
|
||||
p0-compute Ready Active Reachable
|
||||
p1-control Ready Active Reachable
|
||||
p2-control Ready Active Reachable
|
||||
p3-control Ready Active Leader
|
||||
p4-compute Ready Active Reachable
|
||||
p5-compute Ready Active Reachable
|
||||
```
|
||||
|
||||
### Resource Utilization (Current Node)
|
||||
```
|
||||
CPU Load: 0.36, 0.17, 0.20
|
||||
Memory: Total: 28Gi, Used: 2.2Gi, Free: 7.7Gi, Available: 26Gi
|
||||
Disk: Total: 98G, Used: 39G, Available: 55G, Use%: 42%
|
||||
```
|
||||
|
||||
### Docker Daemon Status
|
||||
```
|
||||
Server Version: 29.0.4
|
||||
Storage Driver: overlay2
|
||||
Logging Driver: json-file
|
||||
Cgroup Driver: systemd
|
||||
Kernel Version: 6.8.0-88-generic
|
||||
Operating System: Ubuntu 24.04.3 LTS
|
||||
OSType: linux
|
||||
Architecture: x86_64
|
||||
CPUs: 16
|
||||
Total Memory: 28.31GiB
|
||||
Docker Root Dir: /var/lib/docker
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Recommendations
|
||||
|
||||
### Maintenance Tasks
|
||||
- [ ] Review and prune unused Docker images: `docker image prune -a`
|
||||
- [ ] Review and prune unused volumes: `docker volume prune`
|
||||
- [ ] Check for service updates: Review each service for newer image versions
|
||||
- [ ] Backup GlusterFS volumes to external storage
|
||||
- [ ] Review container logs for errors: `docker service logs <service-name>`
|
||||
- [ ] Test failover by cordoning a node: `docker node update --availability drain <node>`
|
||||
|
||||
### Monitoring Suggestions
|
||||
- Consider deploying Prometheus + Grafana for metrics
|
||||
- Implement centralized logging (ELK, Loki, or similar)
|
||||
- Set up alerting for node failures
|
||||
- Monitor GlusterFS health and replication status
|
||||
- Track container restart counts
|
||||
|
||||
### Security Audit
|
||||
- [ ] Ensure all services use specific version tags (not `latest`)
|
||||
- [ ] Review published ports and restrict unnecessary exposure
|
||||
- [ ] Implement Docker secrets for sensitive configuration
|
||||
- [ ] Enable TLS for all inter-service communication
|
||||
- [ ] Review CrowdSec rules and ban lists
|
||||
- [ ] Audit Traefik configuration for security headers
|
||||
|
||||
---
|
||||
|
||||
## Summary
|
||||
|
||||
This Docker Swarm cluster report was generated on **2025-11-29 17:13:31 UTC**.
|
||||
|
||||
**Cluster Statistics**:
|
||||
- Nodes: 6 (6 managers)
|
||||
- Stacks: 10
|
||||
- Services: 17
|
||||
- Containers: 6
|
||||
- Images: 14
|
||||
- Networks: 6
|
||||
- Volumes: 6
|
||||
|
||||
**Status**: Cluster is operational and all manager nodes are reachable.
|
||||
|
||||
---
|
||||
|
||||
*Report generated by: `generate-swarm-report.sh`*
|
||||
*Script location: `/home/doc/projects/swarm-data/cluster-reports`*
|
||||
@@ -1,4 +1,105 @@
|
||||
services:
|
||||
traefik:
|
||||
image: traefik:v3.6.1
|
||||
ports:
|
||||
- 80:80
|
||||
- 443:443
|
||||
- 8082:8080
|
||||
environment:
|
||||
- CF_DNS_API_TOKEN_FILE=/run/secrets/cloudflare_api_token
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
- ./static.yml:/etc/traefik/traefik.yml:ro
|
||||
- ./dynamic.yml:/etc/traefik/dynamic/dynamic.yml:ro
|
||||
- /home/doc/projects/swarm-data/traefik/certificates:/certificates
|
||||
- /home/doc/projects/swarm-data/traefik/logs:/var/log/traefik
|
||||
secrets:
|
||||
- cloudflare_api_token
|
||||
networks:
|
||||
- frostlabs
|
||||
healthcheck:
|
||||
test: [ "CMD", "wget", "--quiet", "--tries=1", "--spider", "http://localhost:8080/ping" ]
|
||||
interval: 30s
|
||||
timeout: 5s
|
||||
retries: 3
|
||||
start_period: 30s
|
||||
deploy:
|
||||
mode: replicated
|
||||
replicas: 1
|
||||
placement:
|
||||
constraints:
|
||||
- node.labels.task == control
|
||||
|
||||
# crowdsec:
|
||||
# image: crowdsecurity/crowdsec:latest
|
||||
# environment:
|
||||
# # Disable online API enrollment (use for local setup)
|
||||
# - DISABLE_ONLINE_API=false
|
||||
# # Set collections to install
|
||||
# - COLLECTIONS=crowdsecurity/traefik crowdsecurity/http-cve
|
||||
# # Enable Prometheus metrics
|
||||
# - METRICS_PORT=6060
|
||||
# volumes:
|
||||
# # Persistent CrowdSec configuration and data
|
||||
# - /home/doc/projects/swarm-data/crowdsec/config:/etc/crowdsec
|
||||
# - /home/doc/projects/swarm-data/crowdsec/data:/var/lib/crowdsec/data
|
||||
# # Traefik access logs (read-only)
|
||||
# - /home/doc/projects/swarm-data/traefik/logs:/var/log/traefik:ro
|
||||
# # Acquis configuration
|
||||
# - ./acquis.yaml:/etc/crowdsec/acquis.yaml:ro
|
||||
# networks:
|
||||
# - frostlabs
|
||||
# deploy:
|
||||
# mode: replicated
|
||||
# replicas: 1
|
||||
# placement:
|
||||
# constraints:
|
||||
# - node.labels.task == control
|
||||
# restart_policy:
|
||||
# condition: on-failure
|
||||
# delay: 5s
|
||||
# max_attempts: 3
|
||||
# healthcheck:
|
||||
# test: [ "CMD", "cscli", "version" ]
|
||||
# interval: 30s
|
||||
# timeout: 10s
|
||||
# retries: 3
|
||||
# start_period: 60s
|
||||
|
||||
portainer:
|
||||
image: portainer/portainer-ce:latest
|
||||
command: -H tcp://tasks.agent:9001 --tlsskipverify
|
||||
volumes:
|
||||
- /home/doc/projects/swarm-data/portainer:/data
|
||||
networks:
|
||||
- frostlabs
|
||||
ports:
|
||||
- 9000:9000
|
||||
deploy:
|
||||
mode: replicated
|
||||
replicas: 1
|
||||
placement:
|
||||
constraints:
|
||||
- node.labels.task == control
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.swarm.network=frostlabs"
|
||||
- "traefik.http.routers.portainer.rule=Host(`portainer.frostlabs.me`)"
|
||||
- "traefik.http.routers.portainer.entrypoints=websecure"
|
||||
- "traefik.http.routers.portainer.tls=true"
|
||||
- "traefik.http.routers.portainer.tls.certresolver=cloudflare"
|
||||
- "traefik.http.services.portainer.loadbalancer.server.port=9000"
|
||||
|
||||
agent:
|
||||
image: portainer/agent:latest
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
- /var/lib/docker/volumes:/var/lib/docker/volumes
|
||||
networks:
|
||||
- frostlabs
|
||||
deploy:
|
||||
mode: global
|
||||
|
||||
redis:
|
||||
image: redis:alpine
|
||||
command: --save 60 1 --loglevel warning
|
||||
@@ -109,11 +210,15 @@ services:
|
||||
memory: 512M
|
||||
depends_on:
|
||||
- redis
|
||||
|
||||
networks:
|
||||
frostlabs:
|
||||
external: true
|
||||
|
||||
secrets:
|
||||
postgres-master:
|
||||
cloudflare_api_token:
|
||||
external: true
|
||||
auth-key:
|
||||
external: true
|
||||
postgres-master:
|
||||
external: true
|
||||
@@ -1,478 +0,0 @@
|
||||
# CrowdSec with Traefik - User Guide
|
||||
|
||||
## Table of Contents
|
||||
1. [Overview](#overview)
|
||||
2. [Quick Reference](#quick-reference)
|
||||
3. [Managing Decisions (Bans)](#managing-decisions-bans)
|
||||
4. [Applying Protection to Services](#applying-protection-to-services)
|
||||
5. [Monitoring & Metrics](#monitoring--metrics)
|
||||
6. [Collections & Scenarios](#collections--scenarios)
|
||||
7. [Community Integration](#community-integration)
|
||||
8. [Troubleshooting](#troubleshooting)
|
||||
|
||||
## Overview
|
||||
|
||||
CrowdSec is a collaborative IPS (Intrusion Prevention System) that protects your services by:
|
||||
- Analyzing Traefik access logs for malicious patterns
|
||||
- Automatically banning suspicious IPs
|
||||
- Sharing threat intelligence with the community
|
||||
- Providing centralized protection across all Traefik-proxied services
|
||||
|
||||
**Architecture:**
|
||||
- **CrowdSec LAPI** (crowdsec_crowdsec) - Analyzes logs and maintains ban list
|
||||
- **Traefik Bouncer** - Middleware that queries LAPI and blocks banned IPs
|
||||
- **Access Logs** - Traefik logs analyzed by CrowdSec at `/home/doc/projects/swarm-data/traefik/logs/access.log`
|
||||
|
||||
## Quick Reference
|
||||
|
||||
### Access CrowdSec CLI
|
||||
|
||||
All commands must be run on the node where CrowdSec is deployed (p3-control):
|
||||
|
||||
```bash
|
||||
# SSH to the CrowdSec node
|
||||
ssh 10.0.4.14
|
||||
|
||||
# Run cscli commands
|
||||
docker exec $(docker ps -qf name=crowdsec_crowdsec) cscli [command]
|
||||
```
|
||||
|
||||
**Shortcut alias (add to .bashrc):**
|
||||
```bash
|
||||
alias cscli='ssh 10.0.4.14 "docker exec \$(docker ps -qf name=crowdsec_crowdsec) cscli"'
|
||||
```
|
||||
|
||||
### Essential Commands
|
||||
|
||||
```bash
|
||||
# View all active bans
|
||||
cscli decisions list
|
||||
|
||||
# View CrowdSec status
|
||||
cscli metrics
|
||||
|
||||
# View detailed acquisition metrics
|
||||
cscli metrics show acquisition
|
||||
|
||||
# List registered bouncers
|
||||
cscli bouncers list
|
||||
|
||||
# View recent alerts
|
||||
cscli alerts list
|
||||
|
||||
# Check hub status
|
||||
cscli hub list
|
||||
```
|
||||
|
||||
## Managing Decisions (Bans)
|
||||
|
||||
### View Active Bans
|
||||
|
||||
```bash
|
||||
# List all active decisions
|
||||
ssh 10.0.4.14 'docker exec $(docker ps -qf name=crowdsec_crowdsec) cscli decisions list'
|
||||
|
||||
# Filter by IP
|
||||
ssh 10.0.4.14 'docker exec $(docker ps -qf name=crowdsec_crowdsec) cscli decisions list --ip 1.2.3.4'
|
||||
|
||||
# Filter by type
|
||||
ssh 10.0.4.14 'docker exec $(docker ps -qf name=crowdsec_crowdsec) cscli decisions list --type ban'
|
||||
```
|
||||
|
||||
### Manually Ban an IP
|
||||
|
||||
```bash
|
||||
# Ban for 4 hours
|
||||
ssh 10.0.4.14 'docker exec $(docker ps -qf name=crowdsec_crowdsec) cscli decisions add --ip 1.2.3.4 --duration 4h --reason "Manual ban"'
|
||||
|
||||
# Ban for 1 day
|
||||
ssh 10.0.4.14 'docker exec $(docker ps -qf name=crowdsec_crowdsec) cscli decisions add --ip 1.2.3.4 --duration 24h'
|
||||
|
||||
# Permanent ban
|
||||
ssh 10.0.4.14 'docker exec $(docker ps -qf name=crowdsec_crowdsec) cscli decisions add --ip 1.2.3.4 --duration 0'
|
||||
|
||||
# Ban entire subnet
|
||||
ssh 10.0.4.14 'docker exec $(docker ps -qf name=crowdsec_crowdsec) cscli decisions add --range 1.2.3.0/24 --duration 4h'
|
||||
```
|
||||
|
||||
### Unban (Delete Decision)
|
||||
|
||||
```bash
|
||||
# Unban specific IP
|
||||
ssh 10.0.4.14 'docker exec $(docker ps -qf name=crowdsec_crowdsec) cscli decisions delete --ip 1.2.3.4'
|
||||
|
||||
# Delete all decisions
|
||||
ssh 10.0.4.14 'docker exec $(docker ps -qf name=crowdsec_crowdsec) cscli decisions delete --all'
|
||||
```
|
||||
|
||||
### View Alerts
|
||||
|
||||
Alerts show what triggered a ban:
|
||||
|
||||
```bash
|
||||
# List recent alerts
|
||||
ssh 10.0.4.14 'docker exec $(docker ps -qf name=crowdsec_crowdsec) cscli alerts list'
|
||||
|
||||
# View alert details
|
||||
ssh 10.0.4.14 'docker exec $(docker ps -qf name=crowdsec_crowdsec) cscli alerts inspect <alert_id>'
|
||||
|
||||
# Filter alerts by IP
|
||||
ssh 10.0.4.14 'docker exec $(docker ps -qf name=crowdsec_crowdsec) cscli alerts list --ip 1.2.3.4'
|
||||
```
|
||||
|
||||
## Applying Protection to Services
|
||||
|
||||
### Protect Docker Swarm Services
|
||||
|
||||
To protect any service proxied by Traefik, add the `crowdsec` middleware to its labels:
|
||||
|
||||
**Example for a Docker Swarm service:**
|
||||
|
||||
```yaml
|
||||
services:
|
||||
myapp:
|
||||
image: myapp:latest
|
||||
networks:
|
||||
- frostlabs
|
||||
deploy:
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.http.routers.myapp.rule=Host(`myapp.frostlabs.me`)"
|
||||
- "traefik.http.routers.myapp.entrypoints=websecure"
|
||||
- "traefik.http.routers.myapp.tls.certresolver=cloudflare"
|
||||
# Add CrowdSec protection
|
||||
- "traefik.http.routers.myapp.middlewares=crowdsec@file"
|
||||
- "traefik.http.services.myapp.loadbalancer.server.port=8080"
|
||||
```
|
||||
|
||||
### Protect External Services (dynamic.yml)
|
||||
|
||||
For services defined in `/home/doc/projects/homelab/frostlabs/traefik/dynamic.yml`:
|
||||
|
||||
```yaml
|
||||
http:
|
||||
routers:
|
||||
myservice:
|
||||
rule: "Host(`myservice.frostlabs.me`)"
|
||||
entryPoints:
|
||||
- websecure
|
||||
service: myservice
|
||||
middlewares:
|
||||
- crowdsec # Add this line
|
||||
tls:
|
||||
certResolver: cloudflare
|
||||
```
|
||||
|
||||
### Chain Multiple Middlewares
|
||||
|
||||
```yaml
|
||||
# In dynamic.yml
|
||||
http:
|
||||
routers:
|
||||
protected-service:
|
||||
middlewares:
|
||||
- authentik # First: Authentication
|
||||
- crowdsec # Second: IP filtering
|
||||
- rate-limit # Third: Rate limiting
|
||||
```
|
||||
|
||||
After making changes, reload Traefik:
|
||||
```bash
|
||||
docker service update --force traefik_traefik
|
||||
```
|
||||
|
||||
## Monitoring & Metrics
|
||||
|
||||
### Real-time Monitoring
|
||||
|
||||
```bash
|
||||
# Overall metrics
|
||||
ssh 10.0.4.14 'docker exec $(docker ps -qf name=crowdsec_crowdsec) cscli metrics'
|
||||
|
||||
# Log parsing metrics
|
||||
ssh 10.0.4.14 'docker exec $(docker ps -qf name=crowdsec_crowdsec) cscli metrics show acquisition'
|
||||
|
||||
# Scenario metrics (what's triggering)
|
||||
ssh 10.0.4.14 'docker exec $(docker ps -qf name=crowdsec_crowdsec) cscli metrics show scenarios'
|
||||
|
||||
# LAPI metrics (bouncer queries)
|
||||
ssh 10.0.4.14 'docker exec $(docker ps -qf name=crowdsec_crowdsec) cscli metrics show lapi'
|
||||
```
|
||||
|
||||
### View Logs
|
||||
|
||||
```bash
|
||||
# CrowdSec service logs
|
||||
docker service logs crowdsec_crowdsec --tail 50 --follow
|
||||
|
||||
# Traefik logs (on control node)
|
||||
docker service logs traefik_traefik --tail 50 --follow
|
||||
|
||||
# Access log (what CrowdSec analyzes)
|
||||
tail -f /home/doc/projects/swarm-data/traefik/logs/access.log
|
||||
```
|
||||
|
||||
### Check Bouncer Status
|
||||
|
||||
```bash
|
||||
# Verify bouncer is connected
|
||||
ssh 10.0.4.14 'docker exec $(docker ps -qf name=crowdsec_crowdsec) cscli bouncers list'
|
||||
|
||||
# Expected output:
|
||||
# Name IP Address Valid Last API pull Type Version Auth Type
|
||||
# traefik-bouncer ✔️ <timestamp> api-key
|
||||
```
|
||||
|
||||
## Collections & Scenarios
|
||||
|
||||
### View Installed Collections
|
||||
|
||||
Collections are pre-packaged sets of parsers and scenarios:
|
||||
|
||||
```bash
|
||||
# List all collections
|
||||
ssh 10.0.4.14 'docker exec $(docker ps -qf name=crowdsec_crowdsec) cscli collections list'
|
||||
|
||||
# Currently installed:
|
||||
# - crowdsecurity/traefik (Traefik-specific patterns)
|
||||
# - crowdsecurity/http-cve (Common CVE exploits)
|
||||
```
|
||||
|
||||
### Install Additional Collections
|
||||
|
||||
```bash
|
||||
# Install SSH protection (if you expose SSH)
|
||||
ssh 10.0.4.14 'docker exec $(docker ps -qf name=crowdsec_crowdsec) cscli collections install crowdsecurity/sshd'
|
||||
|
||||
# Install WordPress protection
|
||||
ssh 10.0.4.14 'docker exec $(docker ps -qf name=crowdsec_crowdsec) cscli collections install crowdsecurity/wordpress'
|
||||
|
||||
# Install additional HTTP protections
|
||||
ssh 10.0.4.14 'docker exec $(docker ps -qf name=crowdsec_crowdsec) cscli collections install crowdsecurity/base-http-scenarios'
|
||||
|
||||
# Browse available collections
|
||||
ssh 10.0.4.14 'docker exec $(docker ps -qf name=crowdsec_crowdsec) cscli collections list -a'
|
||||
```
|
||||
|
||||
After installing collections, restart CrowdSec:
|
||||
```bash
|
||||
docker service update --force crowdsec_crowdsec
|
||||
```
|
||||
|
||||
### View Active Scenarios
|
||||
|
||||
Scenarios are detection rules:
|
||||
|
||||
```bash
|
||||
# List enabled scenarios
|
||||
ssh 10.0.4.14 'docker exec $(docker ps -qf name=crowdsec_crowdsec) cscli scenarios list'
|
||||
|
||||
# Browse available scenarios
|
||||
ssh 10.0.4.14 'docker exec $(docker ps -qf name=crowdsec_crowdsec) cscli scenarios list -a'
|
||||
|
||||
# Install specific scenario
|
||||
ssh 10.0.4.14 'docker exec $(docker ps -qf name=crowdsec_crowdsec) cscli scenarios install crowdsecurity/http-probing'
|
||||
```
|
||||
|
||||
## Community Integration
|
||||
|
||||
### Enroll in CrowdSec Console
|
||||
|
||||
The Console provides centralized management and community blocklists:
|
||||
|
||||
1. **Create account:** https://app.crowdsec.net/signup
|
||||
|
||||
2. **Enroll your instance:**
|
||||
```bash
|
||||
ssh 10.0.4.14 'docker exec -it $(docker ps -qf name=crowdsec_crowdsec) cscli console enroll <enrollment_key>'
|
||||
```
|
||||
|
||||
3. **Verify enrollment:**
|
||||
```bash
|
||||
ssh 10.0.4.14 'docker exec $(docker ps -qf name=crowdsec_crowdsec) cscli console status'
|
||||
```
|
||||
|
||||
### Benefits of Enrollment
|
||||
|
||||
- **Community Blocklist:** Automatically receive bans from the CrowdSec network
|
||||
- **Centralized Dashboard:** View all your instances in one place
|
||||
- **Alert Management:** Get notifications for attacks
|
||||
- **Analytics:** Detailed attack reports and trends
|
||||
|
||||
### Subscribe to Blocklists
|
||||
|
||||
After enrollment, subscribe to community blocklists:
|
||||
|
||||
```bash
|
||||
# Install blocklist collection
|
||||
ssh 10.0.4.14 'docker exec $(docker ps -qf name=crowdsec_crowdsec) cscli collections install crowdsecurity/seo-bots-whitelist'
|
||||
|
||||
# Enable community blocklist
|
||||
ssh 10.0.4.14 'docker exec $(docker ps -qf name=crowdsec_crowdsec) cscli capi register'
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### CrowdSec Not Reading Logs
|
||||
|
||||
**Check if logs exist:**
|
||||
```bash
|
||||
ls -lh /home/doc/projects/swarm-data/traefik/logs/
|
||||
```
|
||||
|
||||
**Verify acquisition:**
|
||||
```bash
|
||||
ssh 10.0.4.14 'docker exec $(docker ps -qf name=crowdsec_crowdsec) cscli metrics show acquisition'
|
||||
```
|
||||
|
||||
**Restart CrowdSec:**
|
||||
```bash
|
||||
docker service update --force crowdsec_crowdsec
|
||||
```
|
||||
|
||||
### Bouncer Not Blocking
|
||||
|
||||
**Check bouncer is registered:**
|
||||
```bash
|
||||
ssh 10.0.4.14 'docker exec $(docker ps -qf name=crowdsec_crowdsec) cscli bouncers list'
|
||||
```
|
||||
|
||||
**Verify API key in Traefik config:**
|
||||
```bash
|
||||
cat /home/doc/projects/homelab/frostlabs/traefik/dynamic.yml | grep -A 5 crowdseclapikey
|
||||
```
|
||||
|
||||
**Check Traefik can reach CrowdSec:**
|
||||
```bash
|
||||
docker service logs traefik_traefik --tail 50 | grep -i crowdsec
|
||||
```
|
||||
|
||||
### View Decision That Would Block You
|
||||
|
||||
**Test if an IP is banned:**
|
||||
```bash
|
||||
ssh 10.0.4.14 'docker exec $(docker ps -qf name=crowdsec_crowdsec) cscli decisions list --ip <your_ip>'
|
||||
```
|
||||
|
||||
**Whitelist your IP permanently:**
|
||||
|
||||
Edit `/home/doc/projects/homelab/frostlabs/crowdsec/acquis.yaml` and add to CrowdSec config:
|
||||
|
||||
```bash
|
||||
# Create whitelist file
|
||||
ssh 10.0.4.14 'docker exec $(docker ps -qf name=crowdsec_crowdsec) sh -c "echo \"name: crowdsecurity/whitelists
|
||||
description: Whitelist trusted IPs
|
||||
whitelist:
|
||||
reason: trusted network
|
||||
ip:
|
||||
- 10.0.1.0/24
|
||||
- 10.0.4.0/24
|
||||
- <your_public_ip>
|
||||
cidr:
|
||||
- 10.0.0.0/8
|
||||
\" > /etc/crowdsec/parsers/s02-enrich/whitelists.yaml"'
|
||||
|
||||
# Reload CrowdSec
|
||||
docker service update --force crowdsec_crowdsec
|
||||
```
|
||||
|
||||
### Performance Issues
|
||||
|
||||
**Check resource usage:**
|
||||
```bash
|
||||
docker stats $(docker ps -qf name=crowdsec_crowdsec)
|
||||
```
|
||||
|
||||
**Reduce log verbosity in static.yml:**
|
||||
```yaml
|
||||
log:
|
||||
level: ERROR # Change from INFO
|
||||
```
|
||||
|
||||
### Reset CrowdSec Completely
|
||||
|
||||
```bash
|
||||
# Remove all decisions
|
||||
ssh 10.0.4.14 'docker exec $(docker ps -qf name=crowdsec_crowdsec) cscli decisions delete --all'
|
||||
|
||||
# Remove CrowdSec data
|
||||
rm -rf /home/doc/projects/swarm-data/crowdsec/*
|
||||
|
||||
# Redeploy
|
||||
cd /home/doc/projects/homelab/frostlabs/crowdsec
|
||||
docker stack rm crowdsec
|
||||
sleep 10
|
||||
docker stack deploy -c stack.yml crowdsec
|
||||
|
||||
# Regenerate bouncer key (wait 30 seconds first)
|
||||
ssh 10.0.4.14 'docker exec $(docker ps -qf name=crowdsec_crowdsec) cscli bouncers add traefik-bouncer'
|
||||
|
||||
# Update API key in /home/doc/projects/homelab/frostlabs/traefik/dynamic.yml
|
||||
# Then redeploy Traefik
|
||||
docker stack deploy -c stack.yml traefik
|
||||
```
|
||||
|
||||
## Configuration Files
|
||||
|
||||
**Location:** `/home/doc/projects/homelab/frostlabs/crowdsec/`
|
||||
|
||||
- `stack.yml` - Docker Swarm service definition
|
||||
- `acquis.yaml` - Log sources configuration
|
||||
|
||||
**Persistent Data:** `/home/doc/projects/swarm-data/crowdsec/`
|
||||
|
||||
- `config/` - CrowdSec configuration
|
||||
- `data/` - Decision database and state
|
||||
|
||||
**Traefik Logs:** `/home/doc/projects/swarm-data/traefik/logs/`
|
||||
|
||||
- `access.log` - Analyzed by CrowdSec
|
||||
|
||||
## Best Practices
|
||||
|
||||
1. **Start Conservative:** Monitor alerts before enabling aggressive scenarios
|
||||
2. **Whitelist Trusted IPs:** Add your networks to `clientTrustedIPs` in dynamic.yml
|
||||
3. **Test Changes:** Use `cscli decisions add` to test bans before deploying
|
||||
4. **Monitor Metrics:** Regularly check `cscli metrics` to understand what's being blocked
|
||||
5. **Update Regularly:** Keep collections updated with `cscli hub update && cscli hub upgrade`
|
||||
6. **Enable Console:** Enroll for community protection and centralized management
|
||||
7. **Apply Selectively:** Not all services need CrowdSec - use for public-facing services
|
||||
8. **Combine Layers:** Use with authentik for authentication and rate-limit for additional protection
|
||||
|
||||
## Support & Resources
|
||||
|
||||
- **CrowdSec Documentation:** https://docs.crowdsec.net/
|
||||
- **Hub (Collections/Scenarios):** https://hub.crowdsec.net/
|
||||
- **Community Forum:** https://discourse.crowdsec.net/
|
||||
- **Traefik Bouncer Plugin:** https://github.com/maxlerebourg/crowdsec-bouncer-traefik-plugin
|
||||
|
||||
## Maintenance Tasks
|
||||
|
||||
### Weekly
|
||||
|
||||
```bash
|
||||
# Check for new threats
|
||||
ssh 10.0.4.14 'docker exec $(docker ps -qf name=crowdsec_crowdsec) cscli alerts list | head -20'
|
||||
|
||||
# Review metrics
|
||||
ssh 10.0.4.14 'docker exec $(docker ps -qf name=crowdsec_crowdsec) cscli metrics'
|
||||
```
|
||||
|
||||
### Monthly
|
||||
|
||||
```bash
|
||||
# Update hub
|
||||
ssh 10.0.4.14 'docker exec $(docker ps -qf name=crowdsec_crowdsec) cscli hub update'
|
||||
ssh 10.0.4.14 'docker exec $(docker ps -qf name=crowdsec_crowdsec) cscli hub upgrade'
|
||||
|
||||
# Update Docker images
|
||||
docker service update --image crowdsecurity/crowdsec:latest crowdsec_crowdsec
|
||||
docker service update --image traefik:latest traefik_traefik
|
||||
```
|
||||
|
||||
### Quarterly
|
||||
|
||||
- Review and tune scenarios based on false positives
|
||||
- Audit whitelisted IPs
|
||||
- Check for new relevant collections
|
||||
- Review ban durations in scenarios
|
||||
@@ -1,131 +0,0 @@
|
||||
# CrowdSec Quick Reference Card
|
||||
|
||||
## Setup Alias (Recommended)
|
||||
|
||||
Add to your `~/.bashrc`:
|
||||
```bash
|
||||
alias cscli='ssh 10.0.4.14 "docker exec \$(docker ps -qf name=crowdsec_crowdsec) cscli"'
|
||||
```
|
||||
|
||||
Then use: `cscli decisions list` instead of the full command.
|
||||
|
||||
---
|
||||
|
||||
## Most Common Commands
|
||||
|
||||
### View Active Bans
|
||||
```bash
|
||||
ssh 10.0.4.14 'docker exec $(docker ps -qf name=crowdsec_crowdsec) cscli decisions list'
|
||||
```
|
||||
|
||||
### Ban an IP for 4 Hours
|
||||
```bash
|
||||
ssh 10.0.4.14 'docker exec $(docker ps -qf name=crowdsec_crowdsec) cscli decisions add --ip 1.2.3.4 --duration 4h'
|
||||
```
|
||||
|
||||
### Unban an IP
|
||||
```bash
|
||||
ssh 10.0.4.14 'docker exec $(docker ps -qf name=crowdsec_crowdsec) cscli decisions delete --ip 1.2.3.4'
|
||||
```
|
||||
|
||||
### View Recent Alerts (What Triggered Bans)
|
||||
```bash
|
||||
ssh 10.0.4.14 'docker exec $(docker ps -qf name=crowdsec_crowdsec) cscli alerts list'
|
||||
```
|
||||
|
||||
### Check Status & Metrics
|
||||
```bash
|
||||
ssh 10.0.4.14 'docker exec $(docker ps -qf name=crowdsec_crowdsec) cscli metrics'
|
||||
```
|
||||
|
||||
### Verify Bouncer Connected
|
||||
```bash
|
||||
ssh 10.0.4.14 'docker exec $(docker ps -qf name=crowdsec_crowdsec) cscli bouncers list'
|
||||
```
|
||||
|
||||
### View Installed Collections
|
||||
```bash
|
||||
ssh 10.0.4.14 'docker exec $(docker ps -qf name=crowdsec_crowdsec) cscli collections list'
|
||||
```
|
||||
|
||||
### View Traefik Access Logs
|
||||
```bash
|
||||
tail -f /home/doc/projects/swarm-data/traefik/logs/access.log
|
||||
```
|
||||
|
||||
### View CrowdSec Logs
|
||||
```bash
|
||||
docker service logs crowdsec_crowdsec --tail 50 --follow
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Add Protection to a Service
|
||||
|
||||
### Docker Swarm Service (via labels)
|
||||
```yaml
|
||||
deploy:
|
||||
labels:
|
||||
- "traefik.http.routers.myapp.middlewares=crowdsec@file"
|
||||
```
|
||||
|
||||
### External Service (in dynamic.yml)
|
||||
```yaml
|
||||
http:
|
||||
routers:
|
||||
myservice:
|
||||
middlewares:
|
||||
- crowdsec
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Restart CrowdSec
|
||||
```bash
|
||||
docker service update --force crowdsec_crowdsec
|
||||
```
|
||||
|
||||
### Restart Traefik
|
||||
```bash
|
||||
docker service update --force traefik_traefik
|
||||
```
|
||||
|
||||
### Check if Logs Are Being Read
|
||||
```bash
|
||||
ssh 10.0.4.14 'docker exec $(docker ps -qf name=crowdsec_crowdsec) cscli metrics show acquisition'
|
||||
```
|
||||
|
||||
### View Service Status
|
||||
```bash
|
||||
docker service ls | grep -E "crowdsec|traefik"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## File Locations
|
||||
|
||||
| Purpose | Path |
|
||||
|---------|------|
|
||||
| CrowdSec Stack | `/home/doc/projects/homelab/frostlabs/crowdsec/stack.yml` |
|
||||
| Log Config | `/home/doc/projects/homelab/frostlabs/crowdsec/acquis.yaml` |
|
||||
| Traefik Config | `/home/doc/projects/homelab/frostlabs/traefik/dynamic.yml` |
|
||||
| Access Logs | `/home/doc/projects/swarm-data/traefik/logs/access.log` |
|
||||
| CrowdSec Data | `/home/doc/projects/swarm-data/crowdsec/` |
|
||||
|
||||
---
|
||||
|
||||
## Emergency: I Locked Myself Out
|
||||
|
||||
```bash
|
||||
# Delete all bans
|
||||
ssh 10.0.4.14 'docker exec $(docker ps -qf name=crowdsec_crowdsec) cscli decisions delete --all'
|
||||
|
||||
# Or unban specific IP
|
||||
ssh 10.0.4.14 'docker exec $(docker ps -qf name=crowdsec_crowdsec) cscli decisions delete --ip YOUR.IP.HERE'
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
For detailed information, see: `/home/doc/projects/homelab/frostlabs/crowdsec/GUIDE.md`
|
||||
@@ -1,40 +0,0 @@
|
||||
services:
|
||||
crowdsec:
|
||||
image: crowdsecurity/crowdsec:latest
|
||||
environment:
|
||||
# Disable online API enrollment (use for local setup)
|
||||
- DISABLE_ONLINE_API=false
|
||||
# Set collections to install
|
||||
- COLLECTIONS=crowdsecurity/traefik crowdsecurity/http-cve
|
||||
# Enable Prometheus metrics
|
||||
- METRICS_PORT=6060
|
||||
volumes:
|
||||
# Persistent CrowdSec configuration and data
|
||||
- /home/doc/projects/swarm-data/crowdsec/config:/etc/crowdsec
|
||||
- /home/doc/projects/swarm-data/crowdsec/data:/var/lib/crowdsec/data
|
||||
# Traefik access logs (read-only)
|
||||
- /home/doc/projects/swarm-data/traefik/logs:/var/log/traefik:ro
|
||||
# Acquis configuration
|
||||
- ./acquis.yaml:/etc/crowdsec/acquis.yaml:ro
|
||||
networks:
|
||||
- frostlabs
|
||||
deploy:
|
||||
mode: replicated
|
||||
replicas: 1
|
||||
placement:
|
||||
constraints:
|
||||
- node.labels.task == control
|
||||
restart_policy:
|
||||
condition: on-failure
|
||||
delay: 5s
|
||||
max_attempts: 3
|
||||
healthcheck:
|
||||
test: ["CMD", "cscli", "version"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
start_period: 60s
|
||||
|
||||
networks:
|
||||
frostlabs:
|
||||
external: true
|
||||
25
dozzle/stack.yml
Normal file
25
dozzle/stack.yml
Normal file
@@ -0,0 +1,25 @@
|
||||
services:
|
||||
dozzle:
|
||||
image: amir20/dozzle:latest
|
||||
environment:
|
||||
- DOZZLE_MODE=swarm
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
ports:
|
||||
- 8080:8080
|
||||
networks:
|
||||
- frostlabs
|
||||
deploy:
|
||||
mode: global
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.swarm.network=frostlabs"
|
||||
- "traefik.http.routers.dozzle.rule=Host(`logs.frostlabs.me`)"
|
||||
- "traefik.http.routers.dozzle.entrypoints=websecure"
|
||||
- "traefik.http.routers.dozzle.middlewares=authentik@file"
|
||||
- "traefik.http.routers.dozzle.tls=true"
|
||||
- "traefik.http.routers.dozzle.tls.certresolver=cloudflare"
|
||||
- "traefik.http.services.dozzle.loadbalancer.server.port=8080"
|
||||
networks:
|
||||
frostlabs:
|
||||
external: true
|
||||
40
netdata/stack.yml
Normal file
40
netdata/stack.yml
Normal file
@@ -0,0 +1,40 @@
|
||||
services:
|
||||
netdata:
|
||||
image: netdata/netdata:stable
|
||||
networks:
|
||||
- frostlabs
|
||||
cap_add:
|
||||
- SYS_PTRACE
|
||||
- SYS_ADMIN
|
||||
ports:
|
||||
- 19999:19999
|
||||
volumes:
|
||||
- netdataconfig:/etc/netdata
|
||||
- netdatalib:/var/lib/netdata
|
||||
- netdatacache:/var/cache/netdata
|
||||
- /:/host/root:ro,rslave
|
||||
- /etc/passwd:/host/etc/passwd:ro
|
||||
- /etc/group:/host/etc/group:ro
|
||||
- /etc/localtime:/etc/localtime:ro
|
||||
- /proc:/host/proc:ro
|
||||
- /sys:/host/sys:ro
|
||||
- /etc/os-release:/host/etc/os-release:ro
|
||||
- /etc/hostname:/etc/hostname:ro
|
||||
- /var/log:/host/var/log:ro
|
||||
- /var/run/docker.sock:/var/run/docker.sock:ro
|
||||
- /run/dbus:/run/dbus:ro
|
||||
environment:
|
||||
- NETDATA_CLAIM_TOKEN=QGvNtvYVjfMl2chb0jfqID9kEvKMpxkALxeXm-ukHKvTdSbvKwo7w1gwTYvRyzFl9sZs9aL0y0K-1uTVwh3COJxFBwhDgMQX3FfCEsnIX7gjRCcJZZNwV73NvrHfZglZlmOrPfM
|
||||
- NETDATA_CLAIM_URL=https://app.netdata.cloud
|
||||
- NETDATA_CLAIM_ROOMS=d4076c5b-a35f-4564-bf7b-9f67e8374a26
|
||||
deploy:
|
||||
mode: global
|
||||
restart_policy:
|
||||
condition: on-failure
|
||||
volumes:
|
||||
netdataconfig:
|
||||
netdatalib:
|
||||
netdatacache:
|
||||
networks:
|
||||
frostlabs:
|
||||
external: true
|
||||
117
peertube/stack.yml
Normal file
117
peertube/stack.yml
Normal file
@@ -0,0 +1,117 @@
|
||||
services:
|
||||
peertube:
|
||||
image: chocobozzz/peertube:production-bookworm
|
||||
networks:
|
||||
- frostlabs
|
||||
environment:
|
||||
# Database configuration - connecting to existing Postgres
|
||||
- POSTGRES_USER=admin
|
||||
- POSTGRES_PASSWORD=AllOfTheStars+1
|
||||
- POSTGRES_DB=peertube
|
||||
- POSTGRES_HOSTNAME=postgres
|
||||
- POSTGRES_PORT=5432
|
||||
- PEERTUBE_DB_HOSTNAME=postgres
|
||||
- PEERTUBE_DB_PORT=5432
|
||||
- PEERTUBE_DB_USERNAME=admin
|
||||
- PEERTUBE_DB_PASSWORD=AllOfTheStars+1
|
||||
- PEERTUBE_DB_NAME=peertube
|
||||
# Redis configuration
|
||||
- REDIS_HOSTNAME=redis
|
||||
- PEERTUBE_REDIS_HOSTNAME=redis
|
||||
# PeerTube configuration
|
||||
- PEERTUBE_WEBSERVER_HOSTNAME=videos.frostlabs.me
|
||||
- PEERTUBE_WEBSERVER_PORT=443
|
||||
- PEERTUBE_WEBSERVER_HTTPS=true
|
||||
- PEERTUBE_TRUST_PROXY=["127.0.0.1", "loopback", "10.0.1.0/24"]
|
||||
# SMTP configuration - Gmail
|
||||
- PEERTUBE_SMTP_HOSTNAME=smtp.gmail.com
|
||||
- PEERTUBE_SMTP_PORT=587
|
||||
- PEERTUBE_SMTP_USERNAME=frostlabs25@gmail.com
|
||||
- PEERTUBE_SMTP_PASSWORD=tewo awqe ffhw rtun
|
||||
- PEERTUBE_SMTP_FROM=frostlabs25@gmail.com
|
||||
- PEERTUBE_SMTP_TLS=true
|
||||
- PEERTUBE_SMTP_DISABLE_STARTTLS=false
|
||||
- PEERTUBE_ADMIN_EMAIL=frostlabs25@gmail.com
|
||||
# Secrets - loaded from Docker secrets as files
|
||||
- PEERTUBE_SECRET=dfd1cad851c1a5b795131fd2033d46ef80c809b5ac30a3ce8e69b049587138a2
|
||||
# secrets:
|
||||
# - postgres-master
|
||||
# - peertube-key
|
||||
# - gmail-app-password
|
||||
# ports:
|
||||
# - target: 9000
|
||||
# published: 9000
|
||||
# mode: host
|
||||
# - target: 1935
|
||||
# published: 1935
|
||||
# mode: host
|
||||
volumes:
|
||||
# - /home/doc/projects/swarm-data/appdata/peertube/assets:/app/client/dist
|
||||
- /home/doc/projects/swarm-data/peertube/data:/data
|
||||
# healthcheck:
|
||||
# test: [ "CMD", "wget", "--quiet", "--tries=1", "--spider", "http://localhost:9000/api/v1/config" ]
|
||||
# interval: 30s
|
||||
# timeout: 10s
|
||||
# retries: 3
|
||||
# start_period: 60s
|
||||
deploy:
|
||||
mode: replicated
|
||||
replicas: 1
|
||||
placement:
|
||||
constraints:
|
||||
- node.labels.task == compute
|
||||
labels:
|
||||
- traefik.enable=true
|
||||
- traefik.http.routers.peertube.rule=Host(`videos.frostlabs.me`)
|
||||
- traefik.http.routers.peertube.entrypoints=websecure
|
||||
- traefik.http.routers.peertube.tls=true
|
||||
- traefik.http.routers.peertube.tls.certresolver=cloudflare
|
||||
- traefik.http.services.peertube.loadbalancer.server.port=9000
|
||||
|
||||
redis:
|
||||
image: redis:7-alpine
|
||||
networks:
|
||||
- frostlabs
|
||||
volumes:
|
||||
- /home/doc/projects/swarm-data/peertube/redis:/data
|
||||
healthcheck:
|
||||
test: [ "CMD", "redis-cli", "ping" ]
|
||||
interval: 30s
|
||||
timeout: 5s
|
||||
retries: 3
|
||||
deploy:
|
||||
mode: replicated
|
||||
replicas: 1
|
||||
placement:
|
||||
constraints:
|
||||
- node.labels.task == control
|
||||
|
||||
postgres:
|
||||
image: postgres:17-alpine
|
||||
networks:
|
||||
- frostlabs
|
||||
environment:
|
||||
- POSTGRES_USER=admin
|
||||
- POSTGRES_PASSWORD=AllOfTheStars+1
|
||||
- POSTGRES_DB=peertube
|
||||
volumes:
|
||||
- /home/doc/projects/swarm-data/peertube/postgres:/var/lib/postgresql/data
|
||||
ports:
|
||||
- 5432:5432
|
||||
deploy:
|
||||
replicas: 1
|
||||
placement:
|
||||
constraints:
|
||||
- node.labels.task == control
|
||||
|
||||
networks:
|
||||
frostlabs:
|
||||
external: true
|
||||
|
||||
# secrets:
|
||||
# postgres-master:
|
||||
# external: true
|
||||
# peertube-key:
|
||||
# external: true
|
||||
# gmail-app-password:
|
||||
# external: true
|
||||
@@ -1,38 +0,0 @@
|
||||
services:
|
||||
portainer:
|
||||
image: portainer/portainer-ce:latest
|
||||
command: -H tcp://tasks.agent:9001 --tlsskipverify
|
||||
volumes:
|
||||
- /home/doc/projects/swarm-data/portainer:/data
|
||||
networks:
|
||||
- frostlabs
|
||||
ports:
|
||||
- 9000:9000
|
||||
deploy:
|
||||
mode: replicated
|
||||
replicas: 1
|
||||
placement:
|
||||
constraints:
|
||||
- node.labels.task == control
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.swarm.network=frostlabs"
|
||||
- "traefik.http.routers.portainer.rule=Host(`portainer.frostlabs.me`)"
|
||||
- "traefik.http.routers.portainer.entrypoints=websecure"
|
||||
- "traefik.http.routers.portainer.tls=true"
|
||||
- "traefik.http.routers.portainer.tls.certresolver=cloudflare"
|
||||
- "traefik.http.services.portainer.loadbalancer.server.port=9000"
|
||||
|
||||
agent:
|
||||
image: portainer/agent:latest
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
- /var/lib/docker/volumes:/var/lib/docker/volumes
|
||||
networks:
|
||||
- frostlabs
|
||||
deploy:
|
||||
mode: global
|
||||
|
||||
networks:
|
||||
frostlabs:
|
||||
external: true
|
||||
@@ -9,12 +9,12 @@ services:
|
||||
- /home/doc/projects/swarm-data/webservers/production/nginx/nginx.conf:/etc/nginx/nginx.conf:ro
|
||||
- /home/doc/projects/swarm-data/webservers/production/nginx/default.conf:/etc/nginx/conf.d/default.conf:ro
|
||||
- /home/doc/projects/swarm-data/webfiles/production/taylors-development:/usr/share/nginx/html:ro
|
||||
healthcheck:
|
||||
test: [ "CMD-SHELL", "curl -f http://localhost:80 || exit 1" ]
|
||||
interval: 30s
|
||||
timeout: 5s
|
||||
retries: 3
|
||||
start_period: 10s
|
||||
# healthcheck:
|
||||
# test: [ "CMD-SHELL", "curl -f http://localhost:80 || exit 1" ]
|
||||
# interval: 30s
|
||||
# timeout: 5s
|
||||
# retries: 3
|
||||
# start_period: 10s
|
||||
deploy:
|
||||
replicas: 1
|
||||
placement:
|
||||
|
||||
@@ -1,75 +0,0 @@
|
||||
services:
|
||||
traefik:
|
||||
image: traefik:v3.6.1
|
||||
ports:
|
||||
- 80:80
|
||||
- 443:443
|
||||
- 8082:8080
|
||||
environment:
|
||||
- CF_DNS_API_TOKEN_FILE=/run/secrets/cloudflare_api_token
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
- ./static.yml:/etc/traefik/traefik.yml:ro
|
||||
- ./dynamic.yml:/etc/traefik/dynamic/dynamic.yml:ro
|
||||
- /home/doc/projects/swarm-data/traefik/certificates:/certificates
|
||||
- /home/doc/projects/swarm-data/traefik/logs:/var/log/traefik
|
||||
secrets:
|
||||
- cloudflare_api_token
|
||||
networks:
|
||||
- frostlabs
|
||||
healthcheck:
|
||||
test: [ "CMD", "wget", "--quiet", "--tries=1", "--spider", "http://localhost:8080/ping" ]
|
||||
interval: 30s
|
||||
timeout: 5s
|
||||
retries: 3
|
||||
start_period: 30s
|
||||
deploy:
|
||||
mode: replicated
|
||||
replicas: 1
|
||||
placement:
|
||||
constraints:
|
||||
- node.labels.task == control
|
||||
|
||||
crowdsec:
|
||||
image: crowdsecurity/crowdsec:latest
|
||||
environment:
|
||||
# Disable online API enrollment (use for local setup)
|
||||
- DISABLE_ONLINE_API=false
|
||||
# Set collections to install
|
||||
- COLLECTIONS=crowdsecurity/traefik crowdsecurity/http-cve
|
||||
# Enable Prometheus metrics
|
||||
- METRICS_PORT=6060
|
||||
volumes:
|
||||
# Persistent CrowdSec configuration and data
|
||||
- /home/doc/projects/swarm-data/crowdsec/config:/etc/crowdsec
|
||||
- /home/doc/projects/swarm-data/crowdsec/data:/var/lib/crowdsec/data
|
||||
# Traefik access logs (read-only)
|
||||
- /home/doc/projects/swarm-data/traefik/logs:/var/log/traefik:ro
|
||||
# Acquis configuration
|
||||
- ./acquis.yaml:/etc/crowdsec/acquis.yaml:ro
|
||||
networks:
|
||||
- frostlabs
|
||||
deploy:
|
||||
mode: replicated
|
||||
replicas: 1
|
||||
placement:
|
||||
constraints:
|
||||
- node.labels.task == control
|
||||
restart_policy:
|
||||
condition: on-failure
|
||||
delay: 5s
|
||||
max_attempts: 3
|
||||
healthcheck:
|
||||
test: [ "CMD", "cscli", "version" ]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
start_period: 60s
|
||||
|
||||
networks:
|
||||
frostlabs:
|
||||
external: true
|
||||
|
||||
secrets:
|
||||
cloudflare_api_token:
|
||||
external: true
|
||||
52
wiki/stack.yml
Normal file
52
wiki/stack.yml
Normal file
@@ -0,0 +1,52 @@
|
||||
services:
|
||||
wiki:
|
||||
image: ghcr.io/requarks/wiki:2
|
||||
secrets:
|
||||
- postgres-master
|
||||
entrypoint: [ "/bin/sh", "-c" ]
|
||||
command:
|
||||
- |
|
||||
export DB_PASS=$$(cat /run/secrets/postgres-master)
|
||||
node server
|
||||
environment:
|
||||
DB_TYPE: postgres
|
||||
DB_HOST: 10.0.4.10
|
||||
DB_PORT: 5432
|
||||
DB_USER: admin
|
||||
DB_NAME: wiki
|
||||
ports:
|
||||
- "3000:3000"
|
||||
networks:
|
||||
- frostlabs
|
||||
volumes:
|
||||
- /home/doc/projects/swarm-data/wiki/config:/config
|
||||
- /home/doc/projects/swarm-data/wiki/data:/data
|
||||
deploy:
|
||||
replicas: 1
|
||||
placement:
|
||||
constraints:
|
||||
- node.labels.task == compute
|
||||
restart_policy:
|
||||
condition: on-failure
|
||||
delay: 5s
|
||||
max_attempts: 3
|
||||
resources:
|
||||
limits:
|
||||
memory: 2G
|
||||
reservations:
|
||||
memory: 512M
|
||||
labels:
|
||||
- traefik.enable=true
|
||||
- traefik.swarm.network=frostlabs
|
||||
- traefik.http.routers.wiki.rule=Host(`wiki.frostlabs.me`)
|
||||
- traefik.http.routers.wiki.entrypoints=websecure
|
||||
- traefik.http.routers.wiki.tls=true
|
||||
- traefik.http.routers.wiki.tls.certresolver=cloudflare
|
||||
- traefik.http.services.wiki.loadbalancer.server.port=3000
|
||||
networks:
|
||||
frostlabs:
|
||||
external: true
|
||||
|
||||
secrets:
|
||||
postgres-master:
|
||||
external: true
|
||||
Reference in New Issue
Block a user