Files
tuliprox/docker/README.md
T

373 lines
12 KiB
Markdown
Raw Normal View History

# Build docker image
2025-04-23 10:45:45 +02:00
Targets are
- `scratch-final`
- `alpine-final`
Change into the root directory and run:
```shell
2025-04-22 19:43:23 +02:00
# Build for a specific architecture
2025-05-10 17:59:50 +02:00
docker build --rm -f docker/Dockerfile -t tuliprox --target scratch-final --build-arg RUST_TARGET=x86_64-unknown-linux-musl .
2025-04-22 19:43:23 +02:00
2025-05-10 17:59:50 +02:00
docker build --rm -f docker/Dockerfile -t tuliprox --target scratch-final --build-arg RUST_TARGET=aarch64-unknown-linux-musl .
2025-04-22 19:43:23 +02:00
2025-05-10 17:59:50 +02:00
docker build --rm -f docker/Dockerfile -t tuliprox --target scratch-final --build-arg RUST_TARGET=armv7-unknown-linux-musleabihf .
2025-04-22 19:43:23 +02:00
2025-05-10 17:59:50 +02:00
docker build --rm -f docker/Dockerfile -t tuliprox --target scratch-final --build-arg RUST_TARGET=x86_64-apple-darwin .
```
2025-04-23 10:45:45 +02:00
Both targets have the path prefix: `/app`
This will build the complete project and create a docker image.
To start the container, you can use the `docker-compose.yml`
2025-05-10 17:59:50 +02:00
But you need to change `image: ghcr.io/euzu/tuliprox:latest` to `image: tuliprox`
# Manual docker image
You want to build the binary and web folder manually and create a docker image.
2025-05-10 17:59:50 +02:00
To dockerize tuliprox, you need to compile a static build.
The static build can created with `bin\build_lin_static.sh`.
Description of static binary compiling is in the main `README.md`
Then you need to compile the frontend with `yarn build`
Change into the `docker` directory and copy all the needed files (look at the Dockerfile) into the current directory.
To create a docker image type:
2025-05-10 17:59:50 +02:00
`docker -f Dockerfile-manual build -t tuliprox .`
To start the container, you can use the `docker-compose.yml`
2025-05-10 17:59:50 +02:00
But you need to change `image: ghcr.io/euzu/tuliprox:latest` to `image: tuliprox`
2025-05-22 17:39:06 +02:00
Set timezone in docker-compose.yml like
```dockerfile
environment:
- TZ=${TZ:-Europe/Paris}
2025-08-16 00:07:20 +02:00
```
# Docker Container Templates — Deployment Guide
This repository contains ready-to-use Docker Compose templates for a secure reverse proxy stack with VPN egress and CrowdSec protection. It includes **Traefik**, **Gluetun** (WireGuard) with optional proxy sidecars, **CrowdSec** with Traefik integration, and an example **Tuliprox** app wired for reverse proxying.
> **Software baseline:** Traefik v3.5, a current Rust toolchain, and a current Docker/Compose setup.
---
## Legend
| Template | Folder | Purpose | Notable Ports (internal unless published) |
|---|---|---|---|
| **Traefik** | `container-templates/traefik/` | Reverse proxy & TLS (ACME/DNS), dashboard, dynamic security middlewares, optional CrowdSec bouncer. | 80 `web`, 443 `websecure` |
| **Gluetun** | `container-templates/gluetun/` | VPN egress via WireGuard; sidecars provide **SOCKS5**, **HTTP**, and **Shadowsocks** proxies bound to Gluetun’s network stack. | 1080/tcp (HTTP), 1388/tcp+udp (SOCKS5), 9388/tcp+udp (Shadowsocks) |
| **CrowdSec** | `container-templates/crowdsec/` | LAPI + bouncers (Traefik & firewall) to protect services. | LAPI on `127.0.0.1:8080` (host) |
| **Tuliprox** | `container-templates/tuliprox/` | Example application container with Traefik labels and `expose: 8901` for reverse proxying. | 8901 (internal) |
---
## Repository Layout (verified)
```
container-templates/
├─ traefik/
│ ├─ .env
│ ├─ cf-token
│ ├─ config/
│ │ ├─ traefik.yml
│ │ ├─ acme.json (create & chmod 600 if missing)
│ │ └─ dynamic/
│ │ ├─ cdn-default-router.yml
│ │ ├─ crowdsec.yml
│ │ ├─ default-security-headers.yml
│ │ ├─ gluetun-proxys.yml
│ │ ├─ https-redirect.yml
│ │ ├─ real-ip-header.yml
│ │ ├─ strip-ip-header.yml
│ │ └─ tls-security.yml
│ └─ docker-compose.yml
├─ gluetun/
│ ├─ .env.http-proxy
│ ├─ .env.socks5-proxy
│ ├─ .env.ss-proxy
│ ├─ gluetun-01/
│ │ ├─ .env.wg-01
│ │ └─ docker-compose.yml
│ ├─ gluetun-02/
│ │ ├─ .env.wg-02
│ │ └─ docker-compose.yml
│ └─ gluetun-03/
│ ├─ .env.wg-03
│ └─ docker-compose.yml
├─ crowdsec/
│ ├─ .env.cs-bouncer-firewall
│ ├─ .env.cs-bouncer-traefik
│ ├─ crowdsec/
│ │ └─ acquis.d/
│ │ ├─ appsec.yml
│ │ ├─ docker.yml
│ │ ├─ iptables.yml
│ │ ├─ mail.yml
│ │ ├─ sshd.yml
│ │ ├─ system.yml
│ │ └─ traefik.yml
│ ├─ firewall-bouncer/
│ │ └─ config/crowdsec-firewall-bouncer.yaml
│ └─ docker-compose.yml
└─ tuliprox/
└─ docker-compose.yml
```
---
## Prerequisites
1. **Docker & Compose**
2. **Create external networks** used across templates:
```bash
docker network create proxy-net
docker network create crowdsec-net
```
3. **DNS provider token** (e.g., Cloudflare) if you use ACME DNS-01 with Traefik.
---
## 1) Traefik (reverse proxy)
**Folder:** `container-templates/traefik/`
### Files to review
- `.env`
- Fix and fill:
- `TZ=...`
- `TRAEFIK_DASHBOARD_CREDENTIALS=<user:hashed-password>`
- `CF_API_EMAIL=<cloudflare-email>`
- `CF_DNS_API_TOKEN_FILE=/run/secrets/cloudflare`
- `cf-token`
Put **only** your DNS API token string here, then:
```bash
chmod 600 container-templates/traefik/cf-token
```
- `config/traefik.yml`
- Set your ACME email.
- Under `dnsChallenge.provider`, fix provider name if needed (**template shows `cloudclare`; use `cloudflare` or your actual provider**).
- EntryPoints `web`/`websecure` are defined; dynamic files add middlewares.
- `config/acme.json`
- Create if missing and lock down permissions:
```bash
touch container-templates/traefik/config/acme.json
chmod 600 container-templates/traefik/config/acme.json
```
### Start
```bash
docker compose -f container-templates/traefik/docker-compose.yml up -d
docker logs -f traefik
```
### Security middlewares already included
- `https-redirect.yml` (force HTTPS)
- `default-security-headers.yml` (strict defaults for CSP, HSTS, etc.)
- `tls-security.yml` (TLS options)
> Optional: `crowdsec.yml` enables the Traefik bouncer plugin if CrowdSec is running.
1. Add bouncer to your crowdsec engine
```shell
user:~$ docker exec -it crowdsec cscli bouncer add traefik-bouncer
API key for 'traefik-bouncer':
2PbAzuGn9ynn6pYsqoqd98wMJYPA/CIynySN1Lva5H8
Please keep this key since you will not be able to retrieve it!
```
2. Copy the provided key and paste it to your `crowdsec.yml` file
```yaml
crowdsecLapiKey: 2PbAzuGn9ynn6pYsqoqd98wMJYPA/CIynySN1Lva5H8
```
---
## 2) Gluetun (VPN egress + proxy sidecars)
**Folder:** `container-templates/gluetun/`
2025-08-16 00:26:54 +02:00
Each instance (`gluetun-01`, `gluetun-02`, `gluetun-03`) has its own `.env.wg-0x` with WireGuard settings. Sidecars (e.g., `socks5-02`) use `network_mode: service:gluetun-02` to share Gluetun’s network. Otherwise connect the provided proxies within your tuliprox instance through traefik.
2025-08-16 00:07:20 +02:00
### Configure minimum one instance (example: gluetun-02)
1. Edit WireGuard values:
```bash
nano container-templates/gluetun/gluetun-02/.env.wg-02
# WIREGUARD_PRIVATE_KEY=...
# WIREGUARD_ADDRESSES=...
# WIREGUARD_PUBLIC_KEY=...
# WIREGUARD_ENDPOINT_IP=...
# WIREGUARD_ENDPOINT_PORT=51820
# WIREGUARD_MTU=1420
# WIREGUARD_PERSISTENT_KEEPALIVE_INTERVAL=25s
```
2. (Optional) Enable proxy sidecars by editing:
- `container-templates/gluetun/.env.socks5-proxy` (username/password & port 1388)
- `container-templates/gluetun/.env.http-proxy` (HTTP proxy on 1080)
- `container-templates/gluetun/.env.ss-proxy` (Shadowsocks on 9388)
3. Start:
```bash
docker compose -f container-templates/gluetun/gluetun-02/docker-compose.yml up -d
docker logs -f gluetun-02
```
2025-08-16 00:26:54 +02:00
### Test from your Docker host
2025-08-16 00:07:20 +02:00
```bash
# Test SOCKS5(H) via traefik:
docker run --rm curlimages/curl:latest \
-sS -x "socks5h://<USER>:<PASS>@proxy.tuliprox.io:<SOCKS5_PORT>" \
https://ipinfo.io/ip
# Test HTTP(S) proxy via traefik:
docker run --rm curlimages/curl:latest \
-sS -x "https://<USER>:<PASS>@proxy.tuliprox.io:<HTTPS_PROXY_PORT>" \
https://ipinfo.io/ip
```
> Gluetun services are **exposed** to the Docker network by default, not to the host. Publish ports via Traefik or Compose if you really need external access (watch out for abuse/security) or want to use load balancing between your upstream proxy server. Be aware, however, that this can lead to a temporary block if the IP addresses change too quickly between two requests.
---
## 3) CrowdSec (LAPI + bouncers)
**Folder:** `container-templates/crowdsec/`
### Start
```bash
docker compose -f container-templates/crowdsec/docker-compose.yml up -d
docker logs -f crowdsec
```
### Configure
1. Register your crowdsec engine
```bash
docker exec -it crowdsec cscli console enroll -e context cadsgfv0hadfgoisdfhuip
```
2. Add firewall bouncer
```shell
user:~$ docker exec -it crowdsec cscli bouncer add firewall-bouncer
API key for 'firewall-bouncer':
2PbAzuGn9ynn6pYsqoqd98wMJYPA/CIynySN1Lva5H8
Please keep this key since you will not be able to retrieve it!
```
3. Edit your env file
- `.env.cs-bouncer-firewall`
- `CROWDSEC_API_KEY=2PbAzuGn9ynn6pYsqoqd98wMJYPA/CIynySN1Lva5H8`
- `CROWDSEC_LAPI_URL=http://crowdsec:8080`
> The `docker-compose.yml` maps LAPI to `127.0.0.1:8080` on the host, and mounts logs (e.g., `/var/log/traefik/`) plus acquisition files under `crowdsec/acquis.d`.
Once healthy, the Traefik (from `traefik/config/dynamic/crowdsec.yml`) and firewall bouncer can enforce decisions.
---
## 4) Tuliprox (example app)
**Folder:** `container-templates/tuliprox/`
- `docker-compose.yml`:
- Attaches to `proxy-net`.
- `expose: 8901` for reverse proxying.
- Traefik labels are included; adjust hostnames and middlewares as needed.
### Start
```bash
docker compose -f container-templates/tuliprox/docker-compose.yml up -d
docker logs -f tuliprox
```
### Example Traefik labels (adjust to your domain)
If you need to (re)apply labels, here’s a minimal pattern you can adapt:
```yaml
labels:
- "traefik.enable=true"
# HTTP
- "traefik.http.routers.tuliprox.entrypoints=web"
- "traefik.http.routers.tuliprox.rule=Host(`cdn.example.com`)"
- "traefik.http.routers.tuliprox.middlewares=redirect-to-https@file"
# HTTPS
- "traefik.http.routers.tuliprox-secure.entrypoints=websecure"
- "traefik.http.routers.tuliprox-secure.rule=Host(`cdn.example.com`)"
- "traefik.http.routers.tuliprox-secure.tls=true"
- "traefik.http.routers.tuliprox-secure.tls.certresolver=cloudflare"
- "traefik.http.routers.tuliprox-secure.middlewares=default-security-headers@file"
# Internal service port
- "traefik.http.services.tuliprox.loadbalancer.server.port=8901"
```
> The dynamic file `cdn-default-router.yml` includes placeholder hosts (e.g., `cdn.tuliprox.io`). Change these to your domain or disable that router by renaming the file if not used.
---
## Quick Start (end-to-end)
```bash
# 0) Networks (once)
docker network create proxy-net
docker network create crowdsec-net
# 1) Traefik
cd container-templates/traefik
touch config/acme.json && chmod 600 config/acme.json
echo "<your-dns-api-token>" > cf-token && chmod 600 cf-token
# Fix .env and config/traefik.yml (ACME email, dnsChallenge provider, etc.)
docker compose up -d
# 2) Gluetun (e.g., instance 02)
cd ../gluetun/gluetun-02
# Fill .env.wg-02; optionally enable sidecars via ../.env.* files
docker compose up -d
# 3) Tuliprox
cd ../../tuliprox
docker compose up -d
# 4) CrowdSec
cd ../crowdsec
# Fill .env.cs-bouncer-*
docker compose up -d
```
---
## Troubleshooting & Notes
- **External networks missing:**
`network proxy-net/crowdsec-net not found` → create them first (see prerequisites).
- **ACME permissions:**
`config/acme.json` **must** exist and be `chmod 600`, or certificate storage fails.
- **DNS provider typos:**
In `config/traefik.yml`, fix `dnsChallenge.provider` (template shows `cloudclare`; use `cloudflare` or your provider).
- **Expose vs publish:**
Many services are **exposed** to Docker networks only. To reach from the host/Internet, publish ports or front them with Traefik (recommended).
- **Security:**
Be very careful exposing proxy endpoints (SOCKS5/HTTP/Shadowsocks). Require auth, rate-limit, and restrict scope as needed.
---
## Credits / Maintenance
These templates are designed to be composable and conservative by default (HTTPS redirect, strict headers, isolated networks). Review all placeholders marked with `<...>` and domain names like `cdn.tuliprox.io` / `proxy.tuliprox.io` and adjust to your environment.