Skip to content

Commit 2c2fae6

Browse files
Merge pull request #42 from hhftechnology/pangolin
Pangolin
2 parents 6d1f7b9 + 93bda8a commit 2c2fae6

70 files changed

Lines changed: 1433 additions & 1614 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

README.md

Lines changed: 19 additions & 622 deletions
Large diffs are not rendered by default.

cmd/server/main.go

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import (
1818
"crowdsec-manager/internal/api/handlers"
1919
"crowdsec-manager/internal/api/middleware"
2020
"crowdsec-manager/internal/backup"
21+
"crowdsec-manager/internal/cache"
2122
"crowdsec-manager/internal/config"
2223
"crowdsec-manager/internal/configvalidator"
2324
"crowdsec-manager/internal/cron"
@@ -132,7 +133,8 @@ func main() {
132133
api.RegisterBackupRoutes(apiGroup, backupManager, dockerClient)
133134
api.RegisterUpdateRoutes(apiGroup, dockerClient, cfg)
134135
api.RegisterCronRoutes(apiGroup, cronScheduler)
135-
api.RegisterServicesRoutes(apiGroup, dockerClient, db, cfg)
136+
ttlCache := cache.New()
137+
api.RegisterServicesRoutes(apiGroup, dockerClient, db, cfg, ttlCache)
136138
api.RegisterNotificationRoutes(apiGroup, dockerClient, db, cfg)
137139
api.RegisterProfileRoutes(apiGroup, db, cfg, dockerClient)
138140
api.RegisterHostRoutes(apiGroup, multiHost)
@@ -158,12 +160,20 @@ func main() {
158160
// Suppress unused variable warnings — publisher will be used by handlers in Phase 4
159161
_ = publisher
160162

161-
// Serve React frontend static assets and handle client-side routing
163+
// Serve React frontend static assets and handle client-side routing.
164+
// Assets use content-hashed filenames so they can be cached indefinitely.
162165
router.Static("/assets", "./web/dist/assets")
163-
router.StaticFile("/", "./web/dist/index.html")
164-
router.NoRoute(func(c *gin.Context) {
166+
// index.html must not be cached — it references hashed asset URLs that
167+
// change on each build. Without no-cache the browser may serve a stale
168+
// copy (304) that points to old, non-existent JS chunks.
169+
serveIndex := func(c *gin.Context) {
170+
c.Header("Cache-Control", "no-cache, no-store, must-revalidate")
171+
c.Header("Pragma", "no-cache")
172+
c.Header("Expires", "0")
165173
c.File("./web/dist/index.html")
166-
})
174+
}
175+
router.GET("/", func(c *gin.Context) { serveIndex(c) })
176+
router.NoRoute(serveIndex)
167177

168178
// Create HTTP server with production-ready timeouts to prevent resource exhaustion
169179
srv := &http.Server{
Lines changed: 19 additions & 153 deletions
Original file line numberDiff line numberDiff line change
@@ -1,167 +1,33 @@
11
---
22
title: Environment Variables
3-
description: Comprehensive guide to environment configuration
3+
description: Core runtime configuration for CrowdSec Manager
44
---
55

66
# Environment Variables
77

8-
CrowdSec Manager is configured primarily through environment variables passed to the Docker container.
8+
The minimum deployment needs only a small environment set. Add more variables only when your paths or container names differ.
99

10-
## Summary
10+
## Minimum variables (recommended)
1111

12-
**Are any variables absolutely necessary?**
13-
Technically, **no**. The application is designed with sensible defaults for all configuration options. You can run the application without setting any environment variables, provided the default paths (like `./data` and `./logs`) are writable and Docker is available locally.
14-
15-
## Detailed Variable Breakdown
16-
17-
### Core Application Configuration
18-
19-
| Variable | Default | Impact / Description |
20-
| :--- | :--- | :--- |
21-
| `PORT` | `8080` | The HTTP port the manager listens on. Change this if port 8080 is already in use. |
22-
| `ENVIRONMENT` | `production` | Sets the application mode. Use `development` for verbose logging and dev features. |
23-
| `LOG_LEVEL` | `info` | Controls logging verbosity. Options: `debug`, `info`, `warn`, `error`. |
24-
| `LOG_FILE` | `/app/logs/crowdsec-manager.log` | Path where the application log file is written. |
25-
26-
### Docker & Service Discovery
27-
28-
| Variable | Default | Impact / Description |
12+
| Variable | Example | Purpose |
2913
| :--- | :--- | :--- |
30-
| `DOCKER_HOST` | `unix:///var/run/docker.sock` | Address of the Docker daemon. If empty, it uses the default local socket. Set this if connecting to a remote Docker instance. |
31-
| `COMPOSE_FILE` | `/app/docker-compose.yml` | Path to the Docker Compose file. The manager reads this to discover services and manage updates. |
32-
| `*_CONTAINER_NAME` | `crowdsec`, `traefik`, etc. | Overrides for container names if your stack uses different names (e.g., `CROWDSEC_CONTAINER_NAME`, `TRAEFIK_CONTAINER_NAME`). |
33-
| `PANGOLIN_DIR` | `/app` | Base working directory for the application. |
34-
| `CONFIG_DIR` | `/app/config` | Directory where configuration files are stored. |
14+
| `PORT` | `8080` | HTTP port inside the container. |
15+
| `ENVIRONMENT` | `production` | Runtime mode. |
16+
| `TRAEFIK_DYNAMIC_CONFIG` | `/etc/traefik/dynamic_config.yml` | Traefik dynamic config path used by manager actions. |
17+
| `TRAEFIK_CONTAINER_NAME` | `traefik` | Traefik container name in your stack. |
18+
| `TRAEFIK_STATIC_CONFIG` | `/etc/traefik/traefik_config.yml` | Traefik static config path. |
3519

36-
### File Paths & Persistence
20+
## Common optional variables
3721

38-
| Variable | Default | Impact / Description |
22+
| Variable | Default | When to change |
3923
| :--- | :--- | :--- |
40-
| `DATABASE_PATH` | `/app/data/settings.db` | Location of the SQLite database storing app settings. Ensure this path is persistent. |
41-
| `BACKUP_DIR` | `/app/backups` | Directory where backups are stored. |
42-
| `RETENTION_DAYS` | `60` | Number of days to keep backups before auto-deletion. |
43-
44-
### Integrations (Traefik & CrowdSec)
45-
46-
| Variable | Default | Impact / Description |
47-
| :--- | :--- | :--- |
48-
| `TRAEFIK_DYNAMIC_CONFIG` | `/etc/traefik/dynamic_config.yml` | Path to Traefik's dynamic config file. Used to manage middlewares/routers. |
49-
| `TRAEFIK_STATIC_CONFIG` | `/etc/traefik/traefik_config.yml` | Path to Traefik's static config file. |
50-
| `TRAEFIK_ACCESS_LOG` | `/var/log/traefik/access.log` | Path to read Traefik access logs from. |
51-
| `TRAEFIK_ERROR_LOG` | `/var/log/traefik/traefik.log` | Path to read Traefik error logs from. |
52-
| `CROWDSEC_ACQUIS_FILE` | `/etc/crowdsec/acquis.yaml` | Path to CrowdSec's acquisition configuration. |
53-
| `INCLUDE_CROWDSEC` | `true` | Whether to manage CrowdSec container updates/restarts. |
54-
55-
## Recommendation
56-
57-
For a standard deployment, you likely only need to configure:
58-
1. **`PORT`**: If you have a port conflict.
59-
2. **`COMPOSE_FILE`**: If your compose file is not in the default location.
60-
3. **`DOCKER_HOST`**: If running in a complex Docker environment.
61-
62-
Everything else can safely be left to defaults unless you have specific customization needs (like changing log locations or backup retention).
63-
64-
## Handling Custom Paths
65-
66-
A common source of confusion is the difference between **internal container paths** (where the app looks for files) and **external host paths** (where files actually exist on your server).
67-
68-
### The Golden Rule
69-
70-
- **Environment Variables** tell the application **where to look inside the container**.
71-
- **Docker Volumes** map your **real host files** to those **internal container locations**.
72-
73-
### Example: Custom CrowdSec Installation
74-
75-
Suppose your CrowdSec installation is at `/opt/my-custom-crowdsec` instead of the standard `/etc/crowdsec`.
76-
77-
**DO NOT** change the environment variable `CROWDSEC_ACQUIS_FILE` to `/opt/my-custom-crowdsec/acquis.yaml`. The container cannot see your `/opt` directory directly!
78-
79-
**Instead, update your `docker-compose.yml` volumes:**
80-
81-
```yaml
82-
services:
83-
crowdsec-manager:
84-
environment:
85-
# LEAVE THIS AS DEFAULT
86-
- CROWDSEC_ACQUIS_FILE=/etc/crowdsec/acquis.yaml
87-
volumes:
88-
# Map YOUR custom path (left) to the CONTAINER'S expected path (right)
89-
- /opt/my-custom-crowdsec/acquis.yaml:/etc/crowdsec/acquis.yaml:ro
90-
```
91-
92-
By changing the volume mapping, you "trick" the container into seeing your custom file at the standard location it expects. This is almost always the correct way to handle custom paths.
93-
94-
### Common Customization Examples
95-
96-
Here are examples for the most common customization requests. In all cases, **keep the environment variable at its default value** and change the volume mapping in `docker-compose.yml`.
97-
98-
#### 1. Custom CrowdSec Configuration Folder
99-
100-
If your CrowdSec configuration is stored in `/mnt/security/crowdsec`:
101-
102-
```yaml
103-
services:
104-
crowdsec-manager:
105-
environment:
106-
- CROWDSEC_ACQUIS_FILE=/etc/crowdsec/acquis.yaml # Default
107-
volumes:
108-
# Map your custom folder to the standard location
109-
- /mnt/security/crowdsec/acquis.yaml:/etc/crowdsec/acquis.yaml:ro
110-
```
111-
112-
#### 2. Custom Traefik Logs Location
113-
114-
If your Traefik logs are stored in `/var/log/custom-traefik`:
115-
116-
```yaml
117-
services:
118-
crowdsec-manager:
119-
environment:
120-
- TRAEFIK_ACCESS_LOG=/var/log/traefik/access.log # Default
121-
- TRAEFIK_ERROR_LOG=/var/log/traefik/traefik.log # Default
122-
volumes:
123-
# Map your custom log directory to the standard location
124-
- /var/log/custom-traefik:/var/log/traefik:ro
125-
```
126-
127-
#### 3. Custom Traefik Configuration File
128-
129-
If your Traefik static configuration is at `/opt/traefik/traefik.toml`:
130-
131-
```yaml
132-
services:
133-
crowdsec-manager:
134-
environment:
135-
- TRAEFIK_STATIC_CONFIG=/etc/traefik/traefik_config.yml # Default
136-
volumes:
137-
# Map your custom config file to the standard location
138-
- /opt/traefik/traefik.toml:/etc/traefik/traefik_config.yml:ro
139-
```
140-
141-
#### 4. Custom Traefik Dynamic Configuration
142-
143-
If your dynamic configuration is at `/opt/traefik/dynamic/rules.yml`:
144-
145-
```yaml
146-
services:
147-
crowdsec-manager:
148-
environment:
149-
- TRAEFIK_DYNAMIC_CONFIG=/etc/traefik/dynamic_config.yml # Default
150-
volumes:
151-
# Map your custom dynamic config to the standard location
152-
- /opt/traefik/dynamic/rules.yml:/etc/traefik/dynamic_config.yml:ro
153-
```
154-
155-
#### 5. Custom CrowdSec Manager Logs
24+
| `DATABASE_PATH` | `/app/data/settings.db` | If you store app data elsewhere in container. |
25+
| `BACKUP_DIR` | `/app/backups` | If backup path is customized in container. |
26+
| `LOG_LEVEL` | `info` | For troubleshooting (`debug`) or quieter logs. |
27+
| `RETENTION_DAYS` | `60` | To change backup retention policy. |
15628

157-
If you want the manager's own logs to be stored in `/var/log/crowdsec-manager`:
29+
## Notes
15830

159-
```yaml
160-
services:
161-
crowdsec-manager:
162-
environment:
163-
- LOG_FILE=/app/logs/crowdsec-manager.log # Default
164-
volumes:
165-
# Map your custom log directory to the standard location
166-
- /var/log/crowdsec-manager:/app/logs
167-
```
31+
- Keep environment values as in-container paths.
32+
- Use Docker volume mappings to map host paths to those container paths.
33+
- Multi-proxy support is not available in this release.
Lines changed: 8 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,19 @@
11
---
22
title: Networking
3-
description: Network configuration and port management
3+
description: Required Docker network and access model
44
---
55

66
# Networking
77

8-
CrowdSec Manager requires specific network configurations to communicate with other services in your stack.
8+
CrowdSec Manager expects a shared external Docker network named `pangolin`.
99

10-
## The Pangolin Network
11-
12-
The application expects an external Docker network named `pangolin` to exist. This shared network allows CrowdSec Manager to communicate with:
13-
- CrowdSec
14-
- Traefik
15-
- Other integrated services
16-
17-
### Creating the Network
10+
## Required network
1811

1912
```bash
2013
docker network create pangolin
2114
```
2215

23-
### Connecting Services
24-
25-
Ensure all related services in your `docker-compose.yml` are connected to this network:
16+
## Compose requirement
2617

2718
```yaml
2819
networks:
@@ -33,30 +24,10 @@ services:
3324
crowdsec-manager:
3425
networks:
3526
- pangolin
36-
37-
traefik:
38-
networks:
39-
- pangolin
4027
```
4128
42-
## Port Configuration
43-
44-
The application listens on port `8080` inside the container.
45-
46-
### Direct Access
47-
Map the port directly to the host:
29+
## Access patterns
4830
49-
```yaml
50-
ports:
51-
- "8080:8080"
52-
```
53-
54-
### Reverse Proxy (Traefik)
55-
If using Traefik, you don't need to expose the port. Instead, use labels:
56-
57-
```yaml
58-
labels:
59-
- "traefik.enable=true"
60-
- "traefik.http.routers.manager.rule=Host(`manager.example.com`)"
61-
- "traefik.http.services.manager.loadbalancer.server.port=8080"
62-
```
31+
- Keep `expose: "8080"` when a reverse proxy handles routing.
32+
- Use `ports: "8080:8080"` only if you want direct host access.
33+
- Multi-proxy deployment is not supported in this release.
Lines changed: 16 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,23 @@
11
---
22
title: Volumes & Persistence
3-
description: Understanding data persistence and volume mappings
3+
description: Required and optional volume mappings
44
---
55

66
# Volumes & Persistence
77

8-
Proper volume mapping is critical for data persistence and functionality.
8+
The minimum deployment relies on five volume mappings.
99

10-
## Required Volumes
10+
## Required volumes
1111

12-
### Docker Socket
13-
- **Host Path**: `/var/run/docker.sock`
14-
- **Container Path**: `/var/run/docker.sock`
15-
- **Purpose**: Allows the manager to control Docker containers (start, stop, update).
12+
| Host path | Container path | Purpose |
13+
| :--- | :--- | :--- |
14+
| `/var/run/docker.sock` | `/var/run/docker.sock` | Docker API access for service actions. |
15+
| `/root/config` | `/app/config` | Runtime configuration files used by manager workflows. |
16+
| `/root/docker-compose.yml` | `/app/docker-compose.yml` | Compose file used for stack operations. |
17+
| `./backups` | `/app/backups` | Backup artifacts. |
18+
| `./data` | `/app/data` | Persistent settings database and app data. |
1619

17-
### Configuration Directory
18-
- **Host Path**: `/root/config` (example)
19-
- **Container Path**: `/app/config`
20-
- **Purpose**: Stores application configuration files.
21-
22-
### Docker Compose File
23-
- **Host Path**: `/root/docker-compose.yml` (example)
24-
- **Container Path**: `/app/docker-compose.yml`
25-
- **Purpose**: Allows the manager to read and update the stack configuration.
26-
27-
### Data Directory
28-
- **Host Path**: `./data`
29-
- **Container Path**: `/app/data`
30-
- **Purpose**: Persists the SQLite database (`settings.db`). **Critical for saving settings.**
31-
32-
### Backups
33-
- **Host Path**: `./backups`
34-
- **Container Path**: `/app/backups`
35-
- **Purpose**: Stores generated system backups.
36-
37-
### Logs (Optional but Recommended)
38-
- **Host Path**: `/root/config/traefik/logs`
39-
- **Container Path**: `/var/log/traefik`
40-
- **Purpose**: Allows the manager to read and analyze Traefik logs.
41-
42-
## Example Configuration
20+
## Minimum example
4321

4422
```yaml
4523
volumes:
@@ -48,5 +26,9 @@ volumes:
4826
- /root/docker-compose.yml:/app/docker-compose.yml
4927
- ./backups:/app/backups
5028
- ./data:/app/data
51-
- /root/config/traefik/logs:/var/log/traefik
5229
```
30+
31+
## Optional volumes
32+
33+
- Traefik log path mapping, if you want in-app log analysis from host log files.
34+
- Custom config mounts, only when your host paths differ from defaults.

docs/content/docs/features/stack-updates.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ Keep your security stack up to date with the built-in update manager.
1010
## Features
1111

1212
### Version Management
13-
Update Docker images with custom tags. You can specify a specific version (e.g., `v1.2.3`) or use `latest`.
13+
Update Docker images with explicit version tags (for example `1.0.0`).
1414

1515
### Graceful Updates
1616
The system performs updates gracefully:

0 commit comments

Comments
 (0)