This commit is contained in:
2025-10-25 20:11:21 +02:00
commit fd37421245
700 changed files with 211892 additions and 0 deletions

View File

@@ -0,0 +1,499 @@
# Docker Gitea with Traefik Setup
## Overview
Complete setup for self-hosted Gitea with Traefik reverse proxy for secure external access on TrueNAS Scale.
**Stack:**
- Gitea (Git server)
- Traefik (Reverse proxy with automatic SSL)
- Docker Compose
---
## Prerequisites
1. **Domain name** (or subdomain) pointed to your public IP
- Example: `git.yourdomain.com`
- Can use free services like DuckDNS, Cloudflare, etc.
2. **Port forwarding** on your router
- Port 80 (HTTP) → TrueNAS IP
- Port 443 (HTTPS) → TrueNAS IP
3. **SSH access** to TrueNAS Scale
---
## Step 1: Create Datasets
SSH into TrueNAS and create storage locations:
```bash
# Create main directory for docker compose projects
cd /mnt/[your-pool-name]
mkdir -p docker/gitea
mkdir -p docker/traefik
# Create data directories
mkdir -p docker/gitea/data
mkdir -p docker/traefik/letsencrypt
```
Or create via TrueNAS web UI:
- Storage → Create Dataset → `docker`
- Then create subdirectories via SSH or UI
---
## Step 2: Traefik Configuration
### Create Traefik Config Directory
```bash
cd /mnt/[your-pool-name]/docker/traefik
```
### Create `traefik.yml`
```yaml
api:
dashboard: true
insecure: false
entryPoints:
web:
address: ":80"
http:
redirections:
entryPoint:
to: websecure
scheme: https
websecure:
address: ":443"
providers:
docker:
endpoint: "unix:///var/run/docker.sock"
exposedByDefault: false
network: traefik_proxy
certificatesResolvers:
letsencrypt:
acme:
email: your-email@example.com
storage: /letsencrypt/acme.json
httpChallenge:
entryPoint: web
```
### Create `docker-compose.yml` for Traefik
```yaml
version: '3.8'
networks:
traefik_proxy:
name: traefik_proxy
driver: bridge
services:
traefik:
image: traefik:v2.10
container_name: traefik
restart: unless-stopped
security_opt:
- no-new-privileges:true
networks:
- traefik_proxy
ports:
- "80:80"
- "443:443"
environment:
- TZ=America/New_York # Adjust to your timezone
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- ./traefik.yml:/traefik.yml:ro
- ./letsencrypt:/letsencrypt
labels:
- "traefik.enable=true"
# Dashboard
- "traefik.http.routers.traefik.rule=Host(`traefik.yourdomain.com`)"
- "traefik.http.routers.traefik.entrypoints=websecure"
- "traefik.http.routers.traefik.tls.certresolver=letsencrypt"
- "traefik.http.routers.traefik.service=api@internal"
# Basic auth for dashboard (optional but recommended)
# Generate password: echo $(htpasswd -nb admin yourpassword) | sed -e s/\\$/\\$\\$/g
- "traefik.http.routers.traefik.middlewares=traefik-auth"
- "traefik.http.middlewares.traefik-auth.basicauth.users=admin:$$apr1$$xyz$$abc123" # Replace with your hash
```
### Start Traefik
```bash
cd /mnt/[your-pool-name]/docker/traefik
docker compose up -d
```
---
## Step 3: Gitea with Traefik Integration
### Create `docker-compose.yml` for Gitea
```bash
cd /mnt/[your-pool-name]/docker/gitea
```
Create `docker-compose.yml`:
```yaml
version: '3.8'
networks:
traefik_proxy:
external: true
gitea_internal:
driver: bridge
services:
gitea:
image: gitea/gitea:latest
container_name: gitea
restart: unless-stopped
environment:
- USER_UID=1000
- USER_GID=1000
- GITEA__database__DB_TYPE=sqlite3
- GITEA__server__DOMAIN=git.yourdomain.com
- GITEA__server__SSH_DOMAIN=git.yourdomain.com
- GITEA__server__ROOT_URL=https://git.yourdomain.com
- GITEA__server__SSH_PORT=2222
- GITEA__server__SSH_LISTEN_PORT=22
networks:
- traefik_proxy
- gitea_internal
volumes:
- ./data:/data
- /etc/timezone:/etc/timezone:ro
- /etc/localtime:/etc/localtime:ro
ports:
- "2222:22" # SSH for git operations
labels:
- "traefik.enable=true"
- "traefik.docker.network=traefik_proxy"
# HTTP/HTTPS
- "traefik.http.routers.gitea.rule=Host(`git.yourdomain.com`)"
- "traefik.http.routers.gitea.entrypoints=websecure"
- "traefik.http.routers.gitea.tls.certresolver=letsencrypt"
- "traefik.http.services.gitea.loadbalancer.server.port=3000"
```
### Start Gitea
```bash
docker compose up -d
```
---
## Step 4: Router Configuration
### Port Forwarding Rules
On your router, forward these ports to your TrueNAS IP:
| External Port | Internal Port | Protocol | Service |
|--------------|---------------|----------|---------|
| 80 | 80 | TCP | HTTP (Traefik) |
| 443 | 443 | TCP | HTTPS (Traefik) |
| 2222 | 2222 | TCP | SSH (Git operations) |
---
## Step 5: DNS Configuration
Point your domain/subdomain to your public IP:
### Option A: Cloudflare (Recommended)
1. Add A record: `git.yourdomain.com` → Your public IP
2. Optional: Enable Cloudflare proxy (orange cloud)
- Pros: DDoS protection, caching
- Cons: Need to configure Traefik for Cloudflare SSL
### Option B: DuckDNS (Free Dynamic DNS)
1. Create account at duckdns.org
2. Create subdomain: `yourname.duckdns.org`
3. Set up auto-update script on TrueNAS for dynamic IP
### Option C: Your Domain Registrar
1. Add A record: `git` → Your public IP
2. Wait for DNS propagation (up to 24 hours)
---
## Step 6: Initial Gitea Setup
1. Navigate to `https://git.yourdomain.com`
2. Complete first-time setup wizard:
- **Database:** SQLite (default is fine for personal use)
- **SSH Server Domain:** `git.yourdomain.com`
- **SSH Port:** `2222`
- **Base URL:** `https://git.yourdomain.com`
- **Disable registration** (personal use only)
- Create admin account
---
## Step 7: Configure Git Client
### SSH Config
Add to `~/.ssh/config`:
```
Host git.yourdomain.com
HostName git.yourdomain.com
Port 2222
User git
IdentityFile ~/.ssh/id_ed25519 # Or your SSH key
```
### Add SSH Key to Gitea
1. Generate SSH key (if needed):
```bash
ssh-keygen -t ed25519 -C "your-email@example.com"
```
2. Copy public key:
```bash
cat ~/.ssh/id_ed25519.pub
```
3. In Gitea: Settings → SSH/GPG Keys → Add Key
### Test SSH Connection
```bash
ssh -T git@git.yourdomain.com
```
Expected output:
```
Hi there, username! You've successfully authenticated...
```
---
## Step 8: Usage Examples
### Clone Repository
```bash
# HTTPS
git clone https://git.yourdomain.com/username/repo.git
# SSH (recommended)
git clone git@git.yourdomain.com:username/repo.git
```
### Push Existing Repository
```bash
cd /path/to/your/repo
git remote add origin git@git.yourdomain.com:username/repo.git
git push -u origin main
```
---
## Backup Strategy
### Manual Backup
```bash
# Stop Gitea
cd /mnt/[your-pool-name]/docker/gitea
docker compose down
# Backup data directory
tar -czf gitea-backup-$(date +%Y%m%d).tar.gz data/
# Restart Gitea
docker compose up -d
```
### Automated Backup (Gitea Built-in)
Create cron job on TrueNAS:
```bash
# Add to crontab (System Settings → Advanced → Cron Jobs in TrueNAS UI)
0 2 * * * docker exec gitea gitea dump -c /data/gitea/conf/app.ini -f /data/gitea-backup-$(date +\%Y\%m\%d).zip
```
### TrueNAS Snapshots
- Enable periodic snapshots for `docker/gitea` dataset
- Retention: Daily for 7 days, weekly for 4 weeks
- Optional: Replicate to another location
---
## Maintenance
### Update Containers
```bash
# Traefik
cd /mnt/[your-pool-name]/docker/traefik
docker compose pull
docker compose up -d
# Gitea
cd /mnt/[your-pool-name]/docker/gitea
docker compose pull
docker compose up -d
```
### View Logs
```bash
# Traefik
docker logs traefik -f
# Gitea
docker logs gitea -f
```
### Restart Services
```bash
# Restart Gitea
docker restart gitea
# Restart Traefik
docker restart traefik
```
---
## Security Hardening
### 1. Disable Gitea Registration
In Gitea settings or `app.ini`:
```ini
[service]
DISABLE_REGISTRATION = true
REQUIRE_SIGNIN_VIEW = true # Optional: require login to view
```
### 2. Fail2Ban (Optional)
Protect against brute force attacks:
```bash
# Install fail2ban on TrueNAS
# Configure jail for Gitea SSH attempts
```
### 3. Firewall Rules
On TrueNAS, restrict access if needed:
```bash
# Only allow specific IPs (example)
iptables -A INPUT -p tcp --dport 2222 -s YOUR_IP -j ACCEPT
iptables -A INPUT -p tcp --dport 2222 -j DROP
```
### 4. Regular Updates
- Update Docker images monthly
- Monitor Gitea security advisories
- Keep TrueNAS Scale updated
---
## Troubleshooting
### SSL Certificate Not Generated
**Check Traefik logs:**
```bash
docker logs traefik | grep -i error
```
**Common issues:**
- Port 80/443 not properly forwarded
- DNS not pointing to your IP
- Email in traefik.yml incorrect
- Firewall blocking ports
### Can't Access Externally
1. Verify port forwarding on router
2. Check public IP: `curl ifconfig.me`
3. Test DNS: `nslookup git.yourdomain.com`
4. Check Traefik dashboard for routes
### SSH Clone Not Working
1. Verify port 2222 is forwarded
2. Test: `nc -zv git.yourdomain.com 2222`
3. Check SSH key is added in Gitea
4. Verify SSH config (~/.ssh/config)
### Gitea Container Won't Start
```bash
# Check logs
docker logs gitea
# Common issues:
# - Port conflicts (3000 or 2222 in use)
# - Permission issues on data directory
# - Network conflicts
```
---
## Resource Usage
Expected usage on your i7-1065G7 with 16GB RAM:
- **Traefik:** ~30-50 MB RAM, minimal CPU
- **Gitea:** ~100-150 MB RAM, <5% CPU (idle)
- **Total:** ~150-200 MB RAM combined
Plenty of headroom for other services!
---
## Next Steps
- [ ] Decide on domain name (purchase or use DuckDNS)
- [ ] Create datasets on TrueNAS
- [ ] Set up Traefik with docker-compose
- [ ] Configure DNS records
- [ ] Set up router port forwarding
- [ ] Deploy Gitea container
- [ ] Complete Gitea initial setup
- [ ] Configure SSH keys
- [ ] Test external access
- [ ] Set up automated backups
- [ ] Migrate repositories from GitHub
---
## Additional Services to Consider
Once Traefik is set up, you can easily add more services:
- **Uptime Kuma** - Monitoring dashboard
- **Vaultwarden** - Self-hosted Bitwarden
- **Nextcloud** - File sync and sharing
- **Portainer** - Docker management UI
- **Homer/Heimdall** - Homepage dashboard
All use the same Traefik setup for automatic SSL!

View File

@@ -0,0 +1,193 @@
# Git Server Options for TrueNAS
## Overview
Options for self-hosting a git server on TrueNAS, with considerations for features, complexity, and resource requirements.
---
## Option 1: Gitea
**Type:** Lightweight, self-hosted Git service
**Pros:**
- Lightweight and fast (written in Go)
- GitHub-like web interface
- Easy installation via Docker/jail
- Built-in CI/CD (Gitea Actions)
- User management, organizations, teams
- Issue tracking, wiki, pull requests
- Low resource usage (~100-200 MB RAM)
- Active development and community
**Cons:**
- Fewer features than GitLab
- Smaller plugin ecosystem
**Installation:**
- TrueNAS Scale: Deploy via TrueCharts or Docker
- TrueNAS Core: Install in FreeBSD jail
**Best For:** Most home users wanting a full-featured Git platform with minimal overhead
---
## Option 2: GitLab CE (Community Edition)
**Type:** Full-featured DevOps platform
**Pros:**
- Complete DevOps lifecycle (CI/CD, container registry, etc.)
- Professional features (protected branches, merge requests)
- Excellent documentation
- Industry-standard platform
- Built-in runners for automation
**Cons:**
- Resource-heavy (minimum 4GB RAM, recommend 8GB+)
- Slower performance on modest hardware
- More complex to maintain
- Overkill for simple git hosting
**Installation:**
- TrueNAS Scale: Docker container or VM
- Requires dedicated resources
**Best For:** Users who want enterprise features and have hardware to spare
---
## Option 3: Plain Git Server (SSH-based)
**Type:** Bare-bones git via SSH
**Pros:**
- Minimal resource usage
- Simple and reliable
- No web interface complexity
- Uses native TrueNAS SSH access
- Maximum control
**Cons:**
- No web UI
- No pull requests, issues, or collaboration features
- Manual user/permission management
- Command-line only workflow
**Setup:**
```bash
# Create git user and repos directory
# Set up SSH keys
# Initialize bare repos
```
**Best For:** Solo users or small teams comfortable with CLI-only workflow
---
## Option 4: Gogs
**Type:** Painless self-hosted Git service (Gitea's predecessor)
**Pros:**
- Even lighter than Gitea
- Simple and stable
- Easy to set up
- Web interface for basic operations
**Cons:**
- Less actively developed (Gitea forked from it)
- Fewer features than Gitea
- Smaller community
**Best For:** Users wanting minimal resource usage with basic web UI
---
## Option 5: cgit + gitolite
**Type:** Lightweight web viewer + access control
**Pros:**
- Extremely lightweight
- Fast repository browsing (cgit)
- Fine-grained access control (gitolite)
- Battle-tested and stable
**Cons:**
- More complex initial setup
- No modern collaboration features
- Basic web interface (read-only)
- Steeper learning curve
**Best For:** Advanced users prioritizing performance and control
---
## Comparison Matrix
| Feature | Gitea | GitLab CE | Plain Git | Gogs | cgit+gitolite |
|---------|-------|-----------|-----------|------|---------------|
| Resource Usage | Low | High | Minimal | Very Low | Minimal |
| Web UI | Excellent | Excellent | None | Good | Basic |
| Pull Requests | Yes | Yes | No | Yes | No |
| CI/CD | Yes | Yes | No | No | No |
| Setup Complexity | Easy | Medium | Easy | Easy | Hard |
| Active Development | High | High | N/A | Low | Low |
---
## Recommendation
**For most home users: Gitea**
Reasons:
- Best balance of features and resource usage
- Modern, intuitive interface
- Easy to maintain
- Supports collaboration features (PRs, issues)
- Works well on modest hardware
- Can grow with your needs
**Installation on TrueNAS Scale:**
1. Use TrueCharts app or custom Docker container
2. Allocate dataset for persistent storage
3. Configure reverse proxy (optional, for HTTPS)
4. Set up backups of git repositories
---
## Additional Considerations
### Backup Strategy
- Git repositories are already distributed backups
- Still recommended to backup Gitea database and repos
- TrueNAS snapshots + replication to another location
### Access Methods
- SSH: Direct git operations
- HTTPS: Web interface + git operations
- Consider reverse proxy (Nginx/Traefik) for SSL
### Storage Requirements
- Minimal for code repos (MBs to low GBs)
- LFS (Large File Storage) if storing binaries/media
- Plan for growth if hosting many repos
### Security
- Keep software updated
- Use SSH keys or strong passwords
- Consider VPN for external access
- Regular backups
---
## Next Steps
- [ ] Decide on git server solution
- [ ] Plan resource allocation (RAM, CPU, storage)
- [ ] Choose access method (local only vs. external)
- [ ] Set up TrueNAS dataset for git storage
- [ ] Install and configure chosen solution
- [ ] Configure backup strategy
- [ ] Migrate existing repositories (if any)

View File

@@ -0,0 +1,251 @@
# Gitea Setup on TrueNAS Scale
## Installation Options
### Option 1: TrueNAS Scale Apps (Recommended for Beginners)
TrueNAS Scale has a built-in app catalog that includes Gitea.
**Steps:**
1. Navigate to **Apps** in TrueNAS Scale web UI
2. Search for "Gitea"
3. Click **Install**
4. Configure:
- **Application Name:** gitea
- **Storage:** Create new dataset or use existing
- **Network:** Bridge or Host networking
- **Port:** 3000 (web UI), 22 (SSH) - adjust if conflicts
5. Click **Install** and wait for deployment
**Pros:**
- GUI-based installation
- Automatic updates via TrueNAS
- Integrated with TrueNAS management
**Cons:**
- Less control over configuration
- May lag behind latest Gitea releases
---
### Option 2: Custom Docker Container (More Control)
Using TrueNAS Scale's Docker support for more customization.
**Steps:**
1. **Create Dataset**
```
Storage → Create Dataset
Name: gitea_data
```
2. **Create docker-compose.yml** (or use TrueNAS Apps → Discover)
```yaml
version: "3"
services:
gitea:
image: gitea/gitea:latest
container_name: gitea
environment:
- USER_UID=568
- USER_GID=568
- GITEA__database__DB_TYPE=sqlite3
restart: unless-stopped
volumes:
- /mnt/pool/gitea_data:/data
ports:
- "3000:3000"
- "2222:22"
```
3. **Deploy via Portainer or CLI**
**Pros:**
- Full control over versions and configuration
- Easy to backup and migrate
- Can use docker-compose for multi-container setup
**Cons:**
- More manual setup
- Need to manage updates yourself
---
### Option 3: Kubernetes Deployment (Advanced)
TrueNAS Scale runs on Kubernetes, so you can deploy Gitea charts directly.
**Only recommended if you're familiar with Kubernetes**
---
## Initial Configuration
After installation, access Gitea at `http://[truenas-ip]:3000`
### First-Time Setup Wizard
1. **Database Settings:**
- SQLite3 (default, easiest for small setups)
- Or PostgreSQL/MySQL for better performance
2. **General Settings:**
- Site Title: "Your Name's Git"
- Repository Root Path: `/data/git/repositories` (default)
- Git LFS Root Path: `/data/git/lfs` (default)
3. **Server and Third-Party Settings:**
- SSH Server Domain: Your TrueNAS IP or hostname
- SSH Port: 22 (or 2222 if using custom setup)
- Gitea HTTP Listen Port: 3000
- Gitea Base URL: `http://[your-ip]:3000/`
4. **Administrator Account:**
- Create your admin user
- Set secure password
5. Click **Install Gitea**
---
## Post-Installation Configuration
### 1. SSH Access for Git Operations
**If using port 2222 (recommended to avoid conflicts):**
Add to your `~/.ssh/config`:
```
Host git.home
HostName [truenas-ip]
Port 2222
User git
```
Then clone repos with:
```bash
git clone git@git.home:username/repo.git
```
### 2. HTTPS Access (Optional but Recommended)
**Option A: Reverse Proxy (Nginx Proxy Manager)**
- Install Nginx Proxy Manager as another app
- Create proxy host pointing to Gitea
- Add SSL certificate (Let's Encrypt)
**Option B: Built-in HTTPS**
- Configure in Gitea's `app.ini`
- Requires SSL certificate
### 3. Configure Backups
**Gitea Data Locations:**
- Repositories: `/data/git/repositories`
- Database: `/data/gitea.db` (if using SQLite)
- Configuration: `/data/gitea/conf/app.ini`
**TrueNAS Backup Strategy:**
- Periodic snapshots of gitea_data dataset
- Replication to another location
- Or use Gitea's built-in backup command:
```bash
gitea dump -c /data/gitea/conf/app.ini
```
### 4. Performance Tuning
With your 16GB RAM, default settings are fine. If you add many users:
Edit `app.ini`:
```ini
[server]
LFS_START_SERVER = true
[cache]
ENABLED = true
ADAPTER = memory
INTERVAL = 60
[indexer]
ISSUE_INDEXER_TYPE = bleve
REPO_INDEXER_ENABLED = true
```
---
## Usage
### Creating First Repository
1. Log into Gitea web UI
2. Click **+** → **New Repository**
3. Set name, description, visibility
4. Initialize with README if desired
5. Click **Create Repository**
### Pushing Existing Repo
```bash
cd /path/to/your/repo
git remote add origin http://[truenas-ip]:3000/username/repo.git
# or git@git.home:username/repo.git for SSH
git push -u origin main
```
### Migrating from GitHub
1. In Gitea: **+** → **New Migration**
2. Select **GitHub**
3. Enter repo URL
4. Optionally: Add GitHub token for private repos
5. Click **Migrate Repository**
---
## Resource Usage Expectations
With your hardware (i7-1065G7, 16GB RAM):
- **Gitea idle:** ~50-100 MB RAM
- **Gitea active usage:** ~100-200 MB RAM
- **CPU:** Minimal (<5% typically)
Plenty of headroom for other services.
---
## Troubleshooting
### Can't Access Web UI
- Check firewall rules on TrueNAS
- Verify container is running: Apps → Installed
- Check logs in TrueNAS Apps UI
### SSH Clone Not Working
- Verify SSH port is correct (22 or 2222)
- Check SSH keys are added in Gitea: Settings → SSH/GPG Keys
- Test SSH: `ssh -T git@[truenas-ip] -p [port]`
### Slow Performance
- Check TrueNAS system resources (CPU, RAM, disk I/O)
- Consider switching from SQLite to PostgreSQL for large repos
- Enable Gitea caching (see Performance Tuning above)
---
## Next Steps
- [ ] Choose installation method (TrueNAS App vs Custom Docker)
- [ ] Create storage dataset for Gitea data
- [ ] Install Gitea
- [ ] Complete initial setup wizard
- [ ] Create admin account
- [ ] Configure SSH access
- [ ] Set up backup strategy
- [ ] Migrate existing repositories
- [ ] (Optional) Set up HTTPS with reverse proxy
- [ ] (Optional) Configure external access via VPN or port forwarding

View File

@@ -0,0 +1,358 @@
# Integrating Servarr Stack with Traefik
## Your Current Setup
You have a Servarr media automation stack (`servarr.yaml`) with:
- **Gluetun** - VPN container (ProtonVPN)
- **qBittorrent** - Torrent client
- **Sonarr/Radarr/Lidarr** - Media management
- **Prowlarr** - Indexer manager
- **Bazarr** - Subtitle downloader
- **Recyclarr** - Configuration sync
- **Dozzle** - Log viewer
- **Watchtower** - Auto-updater
**Special consideration:** Most services use `network_mode: service:gluetun`, meaning they share gluetun's network namespace for VPN routing.
---
## Challenge: VPN Network Mode
Services using `network_mode: service:gluetun` **cannot** directly connect to the `traefik_proxy` network. They're locked into gluetun's network namespace for VPN routing.
### Options for External Access
**Option 1: Don't Expose VPN Services Externally (Recommended)**
- Keep VPN-routed services local-only
- Access via local network or Tailscale/Wireguard
- Most secure approach
- Expose only Dozzle (log viewer) via Traefik for monitoring
**Option 2: Expose Gluetun to Traefik**
- Connect gluetun container to Traefik network
- Route to services through gluetun's exposed ports
- More complex configuration
- Potential security considerations
**Option 3: Split the Stack**
- Keep VPN services in current stack (local-only)
- Move non-VPN services (Dozzle) to separate stack for Traefik access
---
## Recommended Approach: Hybrid Setup
### Keep VPN Services Local, Expose Dozzle via Traefik
This gives you:
- ✅ Secure VPN routing for download/automation apps (local access only)
- ✅ External access to Dozzle for log monitoring
- ✅ Simple configuration
- ✅ No VPN security compromise
---
## Implementation
### Current Directory Structure
```
/mnt/tank/
├── configs/
│ ├── gluetun/
│ ├── qbittorrent/
│ ├── sonarr/
│ ├── radarr/
│ ├── lidarr/
│ ├── prowlarr/
│ ├── bazarr/
│ ├── recyclarr/
│ └── dozzle/
└── media/
```
### Modified servarr.yaml
**Keep the current file mostly as-is, but extract Dozzle to a separate stack:**
#### Step 1: Deploy Traefik (if not done)
See: [[Traefik Multi-Stack Setup#Step 1]]
#### Step 2: Split Dozzle to Separate Stack
**Remove Dozzle from `servarr.yaml`:**
```yaml
# Remove this section from servarr.yaml:
dozzle:
image: amir20/dozzle:latest
container_name: dozzle
ports:
- 9999:8080
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
restart: unless-stopped
```
**Create `/mnt/tank/stacks/dozzle/docker-compose.yml`:**
```yaml
version: '3.8'
networks:
traefik_proxy:
external: true
services:
dozzle:
image: amir20/dozzle:latest
container_name: dozzle
restart: unless-stopped
networks:
- traefik_proxy
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
environment:
- TZ=Europe/Amsterdam
labels:
- "traefik.enable=true"
- "traefik.docker.network=traefik_proxy"
- "traefik.http.routers.dozzle.rule=Host(`logs.yourdomain.com`)"
- "traefik.http.routers.dozzle.entrypoints=websecure"
- "traefik.http.routers.dozzle.tls.certresolver=cloudflare"
- "traefik.http.services.dozzle.loadbalancer.server.port=8080"
# Optional: Add authentication
- "traefik.http.routers.dozzle.middlewares=dozzle-auth"
- "traefik.http.middlewares.dozzle-auth.basicauth.users=admin:$$apr1$$H6uskkkW$$IgXLP6ewTrSuBkTrqE8wj/"
```
**Deploy Dozzle:**
```bash
mkdir -p /mnt/tank/stacks/dozzle
cd /mnt/tank/stacks/dozzle
# Create docker-compose.yml with content above, then:
docker compose up -d
```
Now accessible at: `https://logs.yourdomain.com`
#### Step 3: Keep Servarr Stack As-Is
Your VPN-routed services remain accessible on local network:
- qBittorrent: `http://truenas-ip:8080`
- Sonarr: `http://truenas-ip:8989`
- Radarr: `http://truenas-ip:7878`
- Prowlarr: `http://truenas-ip:9696`
- Lidarr: `http://truenas-ip:8686`
- Bazarr: `http://truenas-ip:6767`
**Access these via:**
- Local network (current method)
- VPN (Tailscale/Wireguard) for remote access
- SSH tunnel for secure remote access
---
## Alternative: Expose Select Services via Traefik
If you want some *arr services accessible externally (e.g., Sonarr/Radarr for mobile apps):
### Option: Duplicate Ports in Gluetun
Add gluetun to Traefik network and route through it:
**Modified servarr.yaml:**
```yaml
services:
gluetun:
image: qmcgaw/gluetun:latest
container_name: gluetun
cap_add:
- NET_ADMIN
environment:
- VPN_SERVICE_PROVIDER=protonvpn
- VPN_TYPE=wireguard
- WIREGUARD_PRIVATE_KEY=${WIREGUARD_PRIVATE_KEY}
- SERVER_COUNTRIES=Netherlands
- TZ=Europe/Amsterdam
volumes:
- /mnt/tank/configs/gluetun:/gluetun
- /mnt/tank/configs/gluetun-tmp:/tmp/gluetun
ports:
- 8080:8080 # qBittorrent
- 7878:7878 # Radarr
- 8686:8686 # Lidarr
- 8989:8989 # Sonarr
- 9696:9696 # Prowlarr
- 6767:6767 # Bazarr
networks:
- traefik_proxy # Add this
restart: unless-stopped
labels:
# Sonarr via Traefik
- "traefik.enable=true"
- "traefik.docker.network=traefik_proxy"
- "traefik.http.routers.sonarr.rule=Host(`sonarr.yourdomain.com`)"
- "traefik.http.routers.sonarr.entrypoints=websecure"
- "traefik.http.routers.sonarr.tls.certresolver=cloudflare"
- "traefik.http.routers.sonarr.service=sonarr"
- "traefik.http.services.sonarr.loadbalancer.server.port=8989"
# Radarr via Traefik
- "traefik.http.routers.radarr.rule=Host(`radarr.yourdomain.com`)"
- "traefik.http.routers.radarr.entrypoints=websecure"
- "traefik.http.routers.radarr.tls.certresolver=cloudflare"
- "traefik.http.routers.radarr.service=radarr"
- "traefik.http.services.radarr.loadbalancer.server.port=7878"
# Add more services as needed...
networks:
traefik_proxy:
external: true
# ... rest of services remain the same
```
**Security Note:** This exposes your download apps to the internet. Consider:
- Strong authentication in each app
- Traefik basic auth middleware
- Firewall rules limiting access to your IP
- Or stick with VPN-only access
---
## Recommended Final Architecture
```
Internet (Port 80/443)
Traefik
├── Gitea (https://git.yourdomain.com)
├── Dozzle (https://logs.yourdomain.com)
└── [Future Services]
Local Network Only:
Servarr Stack (VPN-routed)
├── Sonarr (http://truenas-ip:8989)
├── Radarr (http://truenas-ip:7878)
├── qBittorrent (http://truenas-ip:8080)
└── [Other *arr apps]
```
**Access Servarr remotely via:**
- Tailscale/Wireguard VPN
- SSH tunnel: `ssh -L 8989:localhost:8989 user@truenas-ip`
---
## Stack Management
### Servarr Stack
```bash
# Start/stop Servarr stack
cd /mnt/tank/stacks/servarr
docker compose up -d
docker compose down
# Update containers (Watchtower handles this automatically)
docker compose pull
docker compose up -d
```
### Dozzle (Traefik-routed)
```bash
cd /mnt/tank/stacks/dozzle
docker compose up -d
docker compose down
```
### Gitea (Traefik-routed)
```bash
cd /mnt/tank/stacks/gitea
docker compose up -d
docker compose down
```
All stacks are independent!
---
## DNS Records for Cloudflare
Add A records:
| Name | Target | Proxy |
|------|--------|-------|
| git | Your-Public-IP | DNS only |
| logs | Your-Public-IP | DNS only |
| traefik | Your-Public-IP | DNS only |
---
## Environment Variables
Create `.env` file in servarr directory for sensitive data:
```bash
# /mnt/tank/stacks/servarr/.env
WIREGUARD_PRIVATE_KEY=your-wireguard-key
```
Reference in docker-compose:
```yaml
environment:
- WIREGUARD_PRIVATE_KEY=${WIREGUARD_PRIVATE_KEY}
```
---
## Security Best Practices
1. **Don't expose VPN-routed services directly to internet**
- Use Tailscale/Wireguard for remote access
- Or use SSH tunnels
2. **Enable authentication on all services**
- Each *arr app has built-in auth
- Configure strong passwords
3. **Use Traefik middlewares for additional security**
- Basic auth
- IP whitelisting
- Rate limiting
4. **Keep Watchtower for auto-updates**
- Already configured in your stack
- Keeps containers patched
---
## Next Steps
- [ ] Deploy Traefik (if not already done)
- [ ] Move Dozzle to separate stack with Traefik labels
- [ ] Deploy Dozzle with external access
- [ ] Keep Servarr services local-only (current setup)
- [ ] Set up Tailscale/Wireguard for secure remote access to Servarr
- [ ] Add DNS records for exposed services
- [ ] Test accessing Dozzle externally
- [ ] Configure authentication for all services
---
## Additional Notes
Your directory structure:
```
/mnt/tank/stacks/
├── traefik/
├── gitea/
├── servarr/ (your existing stack)
└── dozzle/ (optional split from servarr)
```

View File

@@ -0,0 +1,330 @@
# TrueNAS Quick Reference
## Common Commands
### Docker Management
```bash
# View running containers
docker ps
# View all containers (including stopped)
docker ps -a
# View logs
docker logs gitea -f # Follow logs
docker logs traefik --tail 50 # Last 50 lines
# Restart containers
docker restart gitea
docker restart traefik
# Stop/Start with docker-compose
cd /mnt/tank/stacks/gitea
docker compose down
docker compose up -d
# Update containers
docker compose pull
docker compose up -d
# Remove unused images
docker image prune -a
```
### TrueNAS Storage
```bash
# Check pool status
zpool status
# List datasets
zfs list
# Create snapshot
zfs snapshot [pool]/docker/gitea@$(date +%Y%m%d)
# List snapshots
zfs list -t snapshot
# Restore from snapshot
zfs rollback [pool]/docker/gitea@20250125
```
### Network Troubleshooting
```bash
# Check open ports
netstat -tulpn | grep LISTEN
# Test external connectivity
curl -I https://git.yourdomain.com
# Test DNS
nslookup git.yourdomain.com
# Test port forwarding
nc -zv git.yourdomain.com 2222
# Check public IP
curl ifconfig.me
```
### Gitea Specific
```bash
# Enter Gitea container
docker exec -it gitea sh
# Gitea CLI commands (inside container)
gitea admin user list
gitea admin user create --username newuser --email user@example.com --password changeme
gitea dump # Create backup
# View Gitea config
docker exec gitea cat /data/gitea/conf/app.ini
```
### Traefik Specific
```bash
# View Traefik config
docker exec traefik cat /traefik.yml
# Check certificate
docker exec traefik ls -la /letsencrypt
# Restart Traefik to reload config
docker restart traefik
```
---
## File Locations
### On TrueNAS Host
```
/mnt/tank/stacks/
├── traefik/
│ ├── docker-compose.yml
│ ├── traefik.yml
│ └── letsencrypt/
│ └── acme.json
├── gitea/
│ ├── docker-compose.yml
│ └── data/
│ ├── git/
│ │ └── repositories/
│ ├── gitea/
│ │ └── conf/
│ │ └── app.ini
│ └── gitea.db
└── servarr/
└── docker-compose.yml
```
### Important Config Files
- **Traefik config:** `/mnt/tank/stacks/traefik/traefik.yml`
- **Gitea config:** `/mnt/tank/stacks/gitea/data/gitea/conf/app.ini`
- **Gitea repos:** `/mnt/tank/stacks/gitea/data/git/repositories/`
- **SSL certs:** `/mnt/tank/stacks/traefik/letsencrypt/acme.json`
---
## Quick Checks
### Is Everything Running?
```bash
docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}"
```
Expected output:
```
NAMES STATUS PORTS
gitea Up 2 days 0.0.0.0:2222->22/tcp, 3000/tcp
traefik Up 2 days 0.0.0.0:80->80/tcp, 0.0.0.0:443->443/tcp
```
### Check Certificate Expiry
```bash
echo | openssl s_client -servername git.yourdomain.com -connect git.yourdomain.com:443 2>/dev/null | openssl x509 -noout -dates
```
### Disk Usage
```bash
# Docker disk usage
docker system df
# Dataset usage
zfs list | grep docker
```
---
## Backup Commands
### Quick Gitea Backup
```bash
# Create backup
docker exec gitea gitea dump -c /data/gitea/conf/app.ini -f /data/gitea-backup-$(date +%Y%m%d).zip
# Copy backup off server
docker cp gitea:/data/gitea-backup-$(date +%Y%m%d).zip /mnt/tank/backups/
```
### Snapshot Entire Stacks Dataset
```bash
# Create snapshot
zfs snapshot tank/stacks@backup-$(date +%Y%m%d)
# Send to backup location
zfs send tank/stacks@backup-$(date +%Y%m%d) | ssh backup-server "zfs recv backup/truenas-stacks"
```
---
## Git Client Setup
### SSH Config (~/.ssh/config)
```
Host git.yourdomain.com
HostName git.yourdomain.com
Port 2222
User git
IdentityFile ~/.ssh/id_ed25519
```
### Common Git Operations
```bash
# Clone via SSH
git clone git@git.yourdomain.com:username/repo.git
# Clone via HTTPS
git clone https://git.yourdomain.com/username/repo.git
# Add remote to existing repo
git remote add origin git@git.yourdomain.com:username/repo.git
# Push
git push -u origin main
# Test SSH connection
ssh -T git@git.yourdomain.com
```
---
## Maintenance Schedule
### Weekly
- [ ] Check container logs for errors
- [ ] Verify backups completed
### Monthly
- [ ] Update Docker containers
- [ ] Check disk usage
- [ ] Review Gitea security settings
### Quarterly
- [ ] Test disaster recovery (restore from backup)
- [ ] Review access logs
- [ ] Update TrueNAS Scale
---
## Emergency Procedures
### Container Won't Start
```bash
# Check logs
docker logs gitea --tail 100
# Remove and recreate
cd /mnt/tank/stacks/gitea
docker compose down
docker compose up -d
```
### Lost SSL Certificate
```bash
# Remove acme.json to force renewal
rm /mnt/tank/stacks/traefik/letsencrypt/acme.json
docker restart traefik
# Wait a few minutes and check
docker logs traefik | grep -i certificate
```
### Corrupted Database
```bash
# Stop Gitea
cd /mnt/tank/stacks/gitea
docker compose down
# Restore from snapshot
zfs rollback tank/stacks/gitea@[snapshot-name]
# Or restore from Gitea backup
cd /mnt/tank/stacks/gitea/data
unzip gitea-backup-20250125.zip
# Extract files to appropriate locations
# Restart
docker compose up -d
```
---
## Performance Monitoring
```bash
# Container stats
docker stats
# TrueNAS resource usage
top
htop # If installed
# Check I/O
iostat -x 5
```
---
## Useful URLs
When services are running:
- **Gitea:** https://git.yourdomain.com
- **Traefik Dashboard:** https://traefik.yourdomain.com (if configured)
- **TrueNAS UI:** https://[truenas-ip]
---
## Environment Variables Reference
Common environment variables for Gitea:
```yaml
- GITEA__server__DOMAIN=git.yourdomain.com
- GITEA__server__ROOT_URL=https://git.yourdomain.com
- GITEA__server__SSH_PORT=2222
- GITEA__service__DISABLE_REGISTRATION=true
- GITEA__database__DB_TYPE=sqlite3
- GITEA__repository__ENABLE_PUSH_CREATE_USER=true
- GITEA__security__INSTALL_LOCK=true
```
See [Gitea Config Cheat Sheet](https://docs.gitea.io/en-us/config-cheat-sheet/) for full list.

View File

@@ -0,0 +1,287 @@
# Recommended Setup for Your TrueNAS
## Your Situation
- **Hardware:** i7-1065G7, 16GB RAM (plenty of resources)
- **Domain:** Cloudflare-managed domain
- **Requirements:**
- Gitea for self-hosted Git
- Existing Docker stack
- External access via Traefik
- Separate stacks (good practice!)
---
## Recommended Architecture
### Single Traefik Instance + Multiple Independent Stacks
```
Internet (Port 80/443)
Router Port Forwarding
┌─────────────────────────────┐
│ Traefik Container │
│ - SSL Certificates │
│ - Routing │
└──────────┬──────────────────┘
│ traefik_proxy network
┌──────┼──────┐
↓ ↓ ↓
┌───────┐ ┌────────┐ ┌─────────┐
│ Gitea │ │ Other │ │ Future │
│ Stack │ │ Stack │ │ Service │
└───────┘ └────────┘ └─────────┘
```
**Each stack has its own:**
- Directory: `/mnt/[pool]/docker/[service-name]/`
- `docker-compose.yml`
- Data volumes
- Can be started/stopped/updated independently
**Shared:**
- One Traefik instance handles routing for all
- One `traefik_proxy` network connects everything
- One SSL certificate manager (via Cloudflare DNS)
---
## Implementation Steps
### 1. Deploy Traefik (Once, First)
**Location:** `/mnt/tank/stacks/traefik/`
**Key features:**
- Cloudflare DNS challenge for SSL (works even without port 80 exposed)
- Dashboard at `traefik.yourdomain.com`
- Automatic SSL renewal
- HTTP → HTTPS redirect
**See:** [[Traefik Multi-Stack Setup#Step 1]]
### 2. Deploy Gitea Stack
**Location:** `/mnt/tank/stacks/gitea/`
**Connects to:** `traefik_proxy` network (external)
**Exposes:**
- Port 2222 for SSH (git operations)
- Port 3000 internally to Traefik (for web UI)
**Accessible at:** `https://git.yourdomain.com`
**See:** [[Traefik Multi-Stack Setup#Step 2]]
### 3. Connect Your Existing Stack
**Modify your existing stack's `docker-compose.yml`:**
1. Add external network reference:
```yaml
networks:
traefik_proxy:
external: true
```
2. Add network to your service:
```yaml
services:
your-service:
networks:
- traefik_proxy
```
3. Add Traefik labels:
```yaml
labels:
- "traefik.enable=true"
- "traefik.docker.network=traefik_proxy"
- "traefik.http.routers.yourservice.rule=Host(`service.yourdomain.com`)"
- "traefik.http.routers.yourservice.entrypoints=websecure"
- "traefik.http.routers.yourservice.tls.certresolver=cloudflare"
- "traefik.http.services.yourservice.loadbalancer.server.port=INTERNAL_PORT"
```
4. Remove any exposed ports (Traefik handles routing)
**See:** [[Traefik Multi-Stack Setup#Step 3]]
---
## Cloudflare Configuration
### DNS Records
Add A records pointing to your public IP:
```
git.yourdomain.com → Your-Public-IP (DNS only, gray cloud)
traefik.yourdomain.com → Your-Public-IP (DNS only, gray cloud)
service.yourdomain.com → Your-Public-IP (DNS only, gray cloud)
```
**Important:** Use "DNS only" mode, not proxied (gray cloud, not orange).
### API Credentials
For Traefik to manage SSL certificates via Cloudflare DNS:
**Option 1: API Token (Recommended)**
1. Cloudflare Dashboard → Profile → API Tokens
2. Create Token → "Edit zone DNS" template
3. Zone Resources: Include → Specific zone → yourdomain.com
4. Use in Traefik: `CF_DNS_API_TOKEN`
**Option 2: Global API Key**
1. Cloudflare Dashboard → Profile → API Tokens
2. View Global API Key
3. Use in Traefik: `CF_API_EMAIL` + `CF_API_KEY`
---
## Router Port Forwarding
One-time setup:
| External Port | Internal Port | Protocol | Target |
|--------------|---------------|----------|--------|
| 80 | 80 | TCP | TrueNAS IP |
| 443 | 443 | TCP | TrueNAS IP |
| 2222 | 2222 | TCP | TrueNAS IP |
**That's it!** All HTTP/HTTPS traffic goes to Traefik, which routes to the correct service based on domain name.
---
## Directory Structure
Your layout:
```
/mnt/tank/stacks/
├── traefik/
│ ├── docker-compose.yml
│ ├── traefik.yml
│ └── letsencrypt/
│ └── acme.json
├── gitea/
│ ├── docker-compose.yml
│ └── data/
├── servarr/
│ ├── docker-compose.yml (or servarr.yaml)
│ └── ...
└── dozzle/ (optional split from servarr)
└── docker-compose.yml
```
---
## Benefits of This Setup
✅ **Independent stacks** - Update Gitea without touching other services
✅ **One SSL manager** - Traefik handles certificates for all domains
✅ **Easy to add services** - Just add labels and deploy
✅ **Clean separation** - Each service in its own directory
✅ **Professional setup** - Industry-standard architecture
✅ **Low overhead** - Traefik uses ~30-50MB RAM
✅ **Cloudflare integration** - DNS challenge works behind CGNAT
---
## Common Operations
### Start Everything
```bash
# Start Traefik first
cd /mnt/tank/stacks/traefik
docker compose up -d
# Then start services in any order
cd /mnt/tank/stacks/gitea
docker compose up -d
cd /mnt/tank/stacks/servarr
docker compose up -d
```
### Update One Service
```bash
cd /mnt/tank/stacks/gitea
docker compose pull
docker compose up -d
# Other services unaffected
```
### Check Status
```bash
# See all running services
docker ps
# Check what's connected to Traefik
docker network inspect traefik_proxy | grep Name
```
### View Logs
```bash
# Traefik routing logs
docker logs traefik -f
# Service logs
docker logs gitea -f
```
---
## Timeline Estimate
If you already have:
- Cloudflare domain
- Port forwarding access
- SSH to TrueNAS
**Setup time:**
- Traefik deployment: 15 minutes
- Gitea deployment: 10 minutes
- Connect existing stack: 5 minutes
- DNS propagation: 5-30 minutes
- **Total: ~45 minutes to 1 hour**
---
## Next Steps Checklist
- [ ] Get Cloudflare API token/key
- [ ] SSH into TrueNAS
- [ ] Verify `/mnt/tank/stacks/` directory structure
- [ ] Deploy Traefik stack
- [ ] Configure router port forwarding (80, 443, 2222)
- [ ] Add DNS records in Cloudflare
- [ ] Deploy Gitea stack
- [ ] Modify existing stack to connect to Traefik
- [ ] Test access to all services via HTTPS
- [ ] Configure backups
---
## Helpful Documentation
- [[Traefik Multi-Stack Setup]] - Complete multi-stack guide
- [[Quick Reference]] - Common commands
- [[Docker Gitea with Traefik]] - Gitea-specific setup details
---
## Notes
- Your i7-1065G7 can easily handle Traefik + Gitea + several other services
- Expected RAM usage: Traefik (30MB) + Gitea (150MB) = ~200MB total
- Cloudflare DNS challenge means SSL works even if ISP blocks port 80
- Each stack can use different databases, networks, etc. without conflicts

View File

@@ -0,0 +1,71 @@
# Security TODO
## Future Improvements
### Investigate Cloudflare Tunnel as Alternative to Port Forwarding
**Why:**
- No ports opened on router (better security)
- Cloudflare DDoS protection
- Hides home IP address
- Works with existing Traefik setup
**Resources:**
- [Cloudflare Tunnel Documentation](https://developers.cloudflare.com/cloudflare-one/connections/connect-apps/)
- Can work alongside or replace current port forwarding setup
**Status:** To investigate
---
### Look into Pangolin
**Note:** Research what Pangolin is in context of homelab/self-hosting security
**Status:** To investigate
---
## Current Security Measures
### Active:
- ✅ SSH key-based authentication (password auth disabled)
- ✅ Traefik SSL/TLS via Let's Encrypt
- ✅ Basic auth on Traefik dashboard
- ✅ VPN routing for Servarr stack (via Gluetun)
- ✅ Watchtower for automatic container updates
### Planned:
- [ ] Investigate Cloudflare Tunnel
- [ ] Research Pangolin
- [ ] Add Fail2ban for brute force protection
- [ ] Implement Traefik rate limiting middleware
- [ ] Set up IP whitelisting for admin interfaces
- [ ] Regular security audits of exposed services
- [ ] Configure automated backups with encryption
---
## Port Forwarding Currently Active
| Port | Service | Notes |
|------|---------|-------|
| 80 | Traefik HTTP | Auto-redirects to HTTPS |
| 443 | Traefik HTTPS | SSL/TLS encrypted |
| 2222 | Gitea SSH | For git operations |
**Risk Level:** Medium
- Publicly exposed services
- Mitigated by: SSL, authentication, regular updates
**Action Items:**
- Monitor logs regularly
- Keep services updated
- Consider Cloudflare Tunnel migration
---
## References
- [[Traefik Multi-Stack Setup]] - Current setup documentation
- [[Integrating Servarr Stack with Traefik]] - VPN-routed services

View File

@@ -0,0 +1,580 @@
# Traefik Multi-Stack Setup
## Architecture Overview
**One Traefik instance** serves as the reverse proxy for **multiple independent Docker Compose stacks**.
```
┌─────────────────────────────────────────┐
│ Traefik (Port 80/443) │
│ (Handles SSL & Routing) │
└─────────────────┬───────────────────────┘
│ traefik_proxy network
┌─────────┼─────────┬──────────────┐
│ │ │ │
┌───▼───┐ ┌──▼────┐ ┌──▼─────┐ ┌───▼────┐
│ Gitea │ │ Other │ │ Future │ │ Future │
│ Stack │ │ Stack │ │ Stack │ │ Stack │
└───────┘ └───────┘ └────────┘ └────────┘
```
**Benefits:**
- Each service stack is independent (update/restart without affecting others)
- One SSL certificate manager for all services
- Easy to add new services
- Clean separation of concerns
- Each service has its own docker-compose.yml
---
## Directory Structure
```
/mnt/tank/stacks/
├── traefik/ # Traefik stack
│ ├── docker-compose.yml
│ ├── traefik.yml
│ └── letsencrypt/
│ └── acme.json
├── gitea/ # Gitea stack
│ ├── docker-compose.yml
│ └── data/
├── servarr/ # Your existing Servarr stack
│ ├── docker-compose.yml
│ └── data/
└── future-service/ # Future additions
└── docker-compose.yml
```
---
## Step 1: Deploy Traefik (Once)
This is the **only** Traefik instance you need.
### Create Directory
```bash
mkdir -p /mnt/tank/stacks/traefik/letsencrypt
cd /mnt/tank/stacks/traefik
```
### Create `traefik.yml`
```yaml
api:
dashboard: true
insecure: false
entryPoints:
web:
address: ":80"
http:
redirections:
entryPoint:
to: websecure
scheme: https
websecure:
address: ":443"
providers:
docker:
endpoint: "unix:///var/run/docker.sock"
exposedByDefault: false # Only expose containers with traefik.enable=true
network: traefik_proxy # Default network to use
certificatesResolvers:
cloudflare:
acme:
email: your-email@example.com
storage: /letsencrypt/acme.json
# Use DNS challenge for Cloudflare (better for wildcard certs)
dnsChallenge:
provider: cloudflare
resolvers:
- "1.1.1.1:53"
- "1.0.0.1:53"
```
### Create `docker-compose.yml`
```yaml
version: '3.8'
networks:
traefik_proxy:
name: traefik_proxy
driver: bridge
services:
traefik:
image: traefik:v2.10
container_name: traefik
restart: unless-stopped
security_opt:
- no-new-privileges:true
networks:
- traefik_proxy
ports:
- "80:80"
- "443:443"
environment:
- TZ=America/New_York
# Cloudflare API credentials for DNS challenge
- CF_API_EMAIL=your-cloudflare-email@example.com
- CF_API_KEY=your-cloudflare-global-api-key
# Or use API Token (recommended):
# - CF_DNS_API_TOKEN=your-cloudflare-api-token
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- ./traefik.yml:/traefik.yml:ro
- ./letsencrypt:/letsencrypt
labels:
- "traefik.enable=true"
# Dashboard
- "traefik.http.routers.traefik.rule=Host(`traefik.yourdomain.com`)"
- "traefik.http.routers.traefik.entrypoints=websecure"
- "traefik.http.routers.traefik.tls.certresolver=cloudflare"
- "traefik.http.routers.traefik.service=api@internal"
# Basic auth for dashboard
# Generate: echo $(htpasswd -nb admin yourpassword) | sed -e s/\\$/\\$\\$/g
- "traefik.http.routers.traefik.middlewares=traefik-auth"
- "traefik.http.middlewares.traefik-auth.basicauth.users=admin:$$apr1$$H6uskkkW$$IgXLP6ewTrSuBkTrqE8wj/"
```
### Get Cloudflare API Key
**Option A: Global API Key (easier but less secure)**
1. Cloudflare Dashboard → Profile → API Tokens
2. View Global API Key
3. Use with `CF_API_EMAIL` and `CF_API_KEY`
**Option B: API Token (recommended)**
1. Cloudflare Dashboard → Profile → API Tokens → Create Token
2. Use template: "Edit zone DNS"
3. Permissions: Zone → DNS → Edit
4. Zone Resources: Include → Specific zone → yourdomain.com
5. Use with `CF_DNS_API_TOKEN`
### Deploy Traefik
```bash
cd /mnt/tank/stacks/traefik
docker compose up -d
# Check logs
docker logs traefik -f
```
---
## Step 2: Connect Gitea to Traefik
Gitea runs in its **own separate stack**, but connects to Traefik's network.
### Create `docker-compose.yml` for Gitea
```bash
mkdir -p /mnt/tank/stacks/gitea
cd /mnt/tank/stacks/gitea
```
**Key changes from standalone:**
- Connects to **external** `traefik_proxy` network
- Uses Traefik labels for routing
- No exposed ports except SSH (Traefik handles HTTPS)
```yaml
version: '3.8'
networks:
traefik_proxy:
external: true # Uses Traefik's network
gitea_internal:
driver: bridge # Internal network for Gitea (if needed for DB)
services:
gitea:
image: gitea/gitea:latest
container_name: gitea
restart: unless-stopped
environment:
- USER_UID=1000
- USER_GID=1000
- GITEA__database__DB_TYPE=sqlite3
- GITEA__server__DOMAIN=git.yourdomain.com
- GITEA__server__SSH_DOMAIN=git.yourdomain.com
- GITEA__server__ROOT_URL=https://git.yourdomain.com
- GITEA__server__SSH_PORT=2222
- GITEA__server__SSH_LISTEN_PORT=22
networks:
- traefik_proxy # Connect to Traefik
- gitea_internal # Internal network
volumes:
- ./data:/data
- /etc/timezone:/etc/timezone:ro
- /etc/localtime:/etc/localtime:ro
ports:
- "2222:22" # Only SSH needs to be exposed directly
labels:
- "traefik.enable=true"
- "traefik.docker.network=traefik_proxy"
# HTTP/HTTPS routing
- "traefik.http.routers.gitea.rule=Host(`git.yourdomain.com`)"
- "traefik.http.routers.gitea.entrypoints=websecure"
- "traefik.http.routers.gitea.tls.certresolver=cloudflare"
- "traefik.http.services.gitea.loadbalancer.server.port=3000"
```
### Deploy Gitea
```bash
cd /mnt/tank/stacks/gitea
docker compose up -d
# Check logs
docker logs gitea -f
```
---
## Step 3: Connect Your Other Stack to Traefik
For any other service, follow the same pattern:
### Example: Generic Service
```yaml
version: '3.8'
networks:
traefik_proxy:
external: true # Connect to Traefik's network
services:
your-service:
image: your-service-image:latest
container_name: your-service
restart: unless-stopped
networks:
- traefik_proxy
volumes:
- ./data:/data
# NO ports exposed - Traefik handles routing
labels:
- "traefik.enable=true"
- "traefik.docker.network=traefik_proxy"
- "traefik.http.routers.your-service.rule=Host(`service.yourdomain.com`)"
- "traefik.http.routers.your-service.entrypoints=websecure"
- "traefik.http.routers.your-service.tls.certresolver=cloudflare"
- "traefik.http.services.your-service.loadbalancer.server.port=8080" # Internal port
```
### Deploy Your Service
```bash
cd /mnt/tank/stacks/your-service-name
docker compose up -d
```
**That's it!** Traefik automatically:
- Detects the new container
- Creates routes based on labels
- Generates SSL certificate
- Starts routing traffic
---
## Cloudflare DNS Configuration
For each service, add an A record in Cloudflare:
### DNS Records
| Type | Name | Content | Proxy Status |
|------|------|---------|--------------|
| A | git | Your-Public-IP | DNS Only (gray) |
| A | traefik | Your-Public-IP | DNS Only (gray) |
| A | service | Your-Public-IP | DNS Only (gray) |
**Important:** Set to "DNS only" (gray cloud), not proxied (orange cloud), unless you want Cloudflare's proxy in front (requires additional Traefik config).
---
## Port Forwarding
Only forward **once** for Traefik:
| External Port | Internal Port | Protocol | Service |
|--------------|---------------|----------|---------|
| 80 | 80 | TCP | HTTP (Traefik) |
| 443 | 443 | TCP | HTTPS (Traefik) |
| 2222 | 2222 | TCP | SSH (Gitea only) |
**Additional service-specific ports** (like Gitea SSH on 2222) are forwarded individually.
---
## Managing Multiple Stacks
### Start/Stop Individual Stacks
```bash
# Stop Gitea only (doesn't affect Traefik or other services)
cd /mnt/tank/stacks/gitea
docker compose down
# Start Gitea
docker compose up -d
# Restart Gitea
docker compose restart
```
### Update Individual Stacks
```bash
# Update just Gitea
cd /mnt/tank/stacks/gitea
docker compose pull
docker compose up -d
# Update just Traefik
cd /mnt/tank/stacks/traefik
docker compose pull
docker compose up -d
```
### View All Services
```bash
# See all containers connected to Traefik
docker network inspect traefik_proxy
# See all running containers
docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}"
```
---
## Adding New Services (Quick Template)
1. **Create service directory:**
```bash
mkdir -p /mnt/tank/stacks/new-service
cd /mnt/tank/stacks/new-service
```
2. **Create `docker-compose.yml`:**
```yaml
version: '3.8'
networks:
traefik_proxy:
external: true
services:
service-name:
image: service-image:latest
container_name: service-name
restart: unless-stopped
networks:
- traefik_proxy
volumes:
- ./data:/data
labels:
- "traefik.enable=true"
- "traefik.docker.network=traefik_proxy"
- "traefik.http.routers.service-name.rule=Host(`service.yourdomain.com`)"
- "traefik.http.routers.service-name.entrypoints=websecure"
- "traefik.http.routers.service-name.tls.certresolver=cloudflare"
- "traefik.http.services.service-name.loadbalancer.server.port=INTERNAL_PORT"
```
3. **Add DNS record** in Cloudflare: `service.yourdomain.com → Your-IP`
4. **Deploy:**
```bash
docker compose up -d
```
5. **Access:** `https://service.yourdomain.com`
---
## Common Patterns
### Service with Database
```yaml
version: '3.8'
networks:
traefik_proxy:
external: true
internal:
driver: bridge
services:
app:
image: app-image:latest
networks:
- traefik_proxy # For external access
- internal # For database access
labels:
- "traefik.enable=true"
- "traefik.docker.network=traefik_proxy"
- "traefik.http.routers.app.rule=Host(`app.yourdomain.com`)"
- "traefik.http.routers.app.entrypoints=websecure"
- "traefik.http.routers.app.tls.certresolver=cloudflare"
- "traefik.http.services.app.loadbalancer.server.port=3000"
db:
image: postgres:15
networks:
- internal # Only on internal network (not exposed)
volumes:
- ./db-data:/var/lib/postgresql/data
```
### Multiple Domains for One Service
```yaml
labels:
- "traefik.enable=true"
- "traefik.http.routers.app.rule=Host(`app.yourdomain.com`) || Host(`app2.yourdomain.com`)"
- "traefik.http.routers.app.entrypoints=websecure"
- "traefik.http.routers.app.tls.certresolver=cloudflare"
```
### Service with Path Prefix
```yaml
labels:
- "traefik.enable=true"
- "traefik.http.routers.app.rule=Host(`yourdomain.com`) && PathPrefix(`/app`)"
- "traefik.http.routers.app.entrypoints=websecure"
- "traefik.http.routers.app.tls.certresolver=cloudflare"
- "traefik.http.middlewares.app-stripprefix.stripprefix.prefixes=/app"
- "traefik.http.routers.app.middlewares=app-stripprefix"
```
---
## Troubleshooting Multi-Stack Setup
### Service Not Accessible
```bash
# Check if container is on traefik_proxy network
docker network inspect traefik_proxy
# Check Traefik logs for routing issues
docker logs traefik | grep -i error
# Verify DNS resolves correctly
nslookup service.yourdomain.com
# Check if Traefik sees the service
docker exec traefik wget -O- http://localhost:8080/api/http/routers | grep service-name
```
### SSL Certificate Issues
```bash
# Check Traefik logs for ACME errors
docker logs traefik | grep -i acme
# Verify Cloudflare credentials are correct
docker exec traefik env | grep CF_
# Delete acme.json to force renewal (last resort)
docker compose down
rm letsencrypt/acme.json
docker compose up -d
```
### Network Conflicts
```bash
# List all networks
docker network ls
# Inspect traefik_proxy network
docker network inspect traefik_proxy
# Recreate network if needed
docker network rm traefik_proxy
cd /mnt/[pool]/docker/traefik
docker compose up -d
```
---
## Stack Independence Benefits
✅ **Update one service without affecting others**
```bash
cd /mnt/tank/stacks/gitea
docker compose pull && docker compose up -d
# Other services keep running
```
✅ **Restart one service without downtime for others**
```bash
docker restart gitea
# Traefik and other services unaffected
```
✅ **Remove a service cleanly**
```bash
cd /mnt/tank/stacks/old-service
docker compose down
rm -rf /mnt/tank/stacks/old-service
# Done! No leftover configs in other stacks
```
✅ **Easy backups per service**
```bash
tar -czf gitea-backup.tar.gz /mnt/tank/stacks/gitea/
tar -czf servarr-backup.tar.gz /mnt/tank/stacks/servarr/
```
---
## Next Steps
- [ ] Deploy Traefik (one time)
- [ ] Get Cloudflare API credentials
- [ ] Configure DNS records for services
- [ ] Deploy Gitea stack
- [ ] Connect your existing stack to Traefik
- [ ] Test accessing all services via HTTPS
- [ ] Set up automated backups per stack
---
## Example Full Setup
```
/mnt/tank/stacks/
├── traefik/
│ ├── docker-compose.yml # Traefik
│ ├── traefik.yml
│ └── letsencrypt/
├── gitea/
│ ├── docker-compose.yml # Gitea stack
│ └── data/
├── servarr/
│ ├── docker-compose.yml # Servarr stack (your existing)
│ └── ...
├── nextcloud/
│ ├── docker-compose.yml # Nextcloud stack
│ ├── app-data/
│ └── db-data/
└── vaultwarden/
├── docker-compose.yml # Vaultwarden stack
└── data/
```
Each stack is independent, but all route through Traefik! 🎉

View File

@@ -0,0 +1,72 @@
# TrueNAS Server
## Overview
Documentation for TrueNAS home server setup, configuration, and services.
## System Information
- **Type:** TrueNAS Scale
- **Hardware:**
- CPU: Intel Core i7-1065G7 (4 cores, 8 threads @ 1.30GHz base)
- RAM: 16GB
- Form Factor: Laptop
- **Storage Configuration:**
- Pool: `tank`
- Docker Stacks: `/mnt/tank/stacks/`
- Configs: `/mnt/tank/configs/`
- Media: `/mnt/tank/media/`
- **Timezone:** Europe/Amsterdam
- **Network:** TBD
## Services & Applications
**Currently Deployed:**
- Servarr Stack (VPN-routed media automation) - See [[servarr.yaml]]
- Gluetun (ProtonVPN), qBittorrent, Sonarr, Radarr, Lidarr, Prowlarr, Bazarr, Recyclarr, Dozzle, Watchtower
**Start Here:**
- [[Recommended Setup]] - ⭐ Your complete setup plan (Traefik + Gitea + existing stack)
**Detailed Guides:**
- [[Traefik Multi-Stack Setup]] - One Traefik instance for multiple service stacks
- [[Integrating Servarr Stack with Traefik]] - How to connect your existing Servarr stack
- [[Docker Gitea with Traefik]] - Docker deployment with Traefik reverse proxy
- [[Gitea Setup]] - Alternative: TrueNAS Apps installation (not using this)
- [[Git Server Options]] - Comparison of all git server options
**Reference:**
- [[Quick Reference]] - Common commands and troubleshooting
- [[VS Code SSH Setup]] - Configure VS Code for remote editing
- [[Security TODO]] - Future security improvements and research
## Configuration
### Datasets
### Shares
### Snapshots & Replication
## Maintenance
### Backup Strategy
### Update Schedule
## Resources
- [TrueNAS Documentation](https://www.truenas.com/docs/)
- [TrueNAS Community Forums](https://www.truenas.com/community/)
- [Traefik Documentation](https://doc.traefik.io/traefik/)
- [Gitea Documentation](https://docs.gitea.io/)
## Notes
6XdKFJCp3hYPuKXD6AgP0m5KbxjueQzB

View File

@@ -0,0 +1,405 @@
# VS Code SSH Setup for TrueNAS
## Overview
Configure VS Code to SSH into your TrueNAS server for easy file editing and terminal access.
---
## Prerequisites
1. **VS Code installed** on your local machine
2. **Remote - SSH extension** installed in VS Code
3. **SSH access enabled** on TrueNAS
4. **TrueNAS IP address** or hostname
---
## Step 1: Install VS Code Extension
### Install Remote - SSH Extension
1. Open VS Code
2. Click Extensions icon (or `Ctrl+Shift+X`)
3. Search for: **Remote - SSH**
4. Install the extension by Microsoft
5. Reload VS Code if prompted
**Extension ID:** `ms-vscode-remote.remote-ssh`
---
## Step 2: Enable SSH on TrueNAS (if not already enabled)
### TrueNAS Scale
1. Navigate to **System Settings → Services**
2. Find **SSH** service
3. Click **Edit** (pencil icon)
4. Configure:
-**Allow Password Authentication** (initially, we'll use keys later)
-**Allow TCP Forwarding**
- Port: **22** (default)
5. Click **Save**
6. **Start** the SSH service
7.**Start Automatically** (enable)
---
## Step 3: Find Your TrueNAS Connection Details
### Get TrueNAS IP Address
**Option A: From TrueNAS UI**
- Dashboard → Top right shows IP address
**Option B: From Shell**
```bash
ip addr show | grep inet
```
### Get Your Username
**Default admin user:** `admin`
Or check: **Credentials → Local Users**
---
## Step 4: Generate SSH Key (Recommended)
**On your local Windows machine (WSL or PowerShell):**
### Using WSL (Recommended)
```bash
# Generate SSH key
ssh-keygen -t ed25519 -C "truenas-access"
# Default location: ~/.ssh/id_ed25519
# Press Enter to accept
# Enter passphrase (optional but recommended)
# Copy public key to TrueNAS
ssh-copy-id admin@truenas-ip
# Or manually copy:
cat ~/.ssh/id_ed25519.pub
# Then paste into TrueNAS UI
```
### Using PowerShell (Alternative)
```powershell
# Generate SSH key
ssh-keygen -t ed25519 -C "truenas-access"
# Location: C:\Users\Vince\.ssh\id_ed25519
# Copy public key
Get-Content C:\Users\Vince\.ssh\id_ed25519.pub
```
### Add Public Key to TrueNAS
1. TrueNAS UI → **Credentials → Local Users**
2. Click **Edit** on your user (admin)
3. Scroll to **SSH Public Key**
4. Paste your public key
5. Click **Save**
---
## Step 5: Configure SSH Config File
Create/edit SSH config for easy connections.
### Location
**WSL:** `~/.ssh/config`
**Windows:** `C:\Users\Vince\.ssh\config`
### Add TrueNAS Configuration
```bash
Host truenas
HostName 192.168.1.XXX # Your TrueNAS IP
User admin # Your TrueNAS username
Port 22
IdentityFile ~/.ssh/id_ed25519 # Path to your SSH key
ForwardAgent yes
ServerAliveInterval 60
ServerAliveCountMax 3
# Optional: Shorter alias
Host nas
HostName 192.168.1.XXX
User admin
IdentityFile ~/.ssh/id_ed25519
```
**Replace:** `192.168.1.XXX` with your actual TrueNAS IP
### Test SSH Connection
```bash
ssh truenas
# or
ssh nas
```
Should connect without password!
---
## Step 6: Connect VS Code to TrueNAS
### Method 1: Using Command Palette
1. Open VS Code
2. Press `Ctrl+Shift+P` (or `F1`)
3. Type: **Remote-SSH: Connect to Host**
4. Select **truenas** (or **nas**) from the list
- Or type: `admin@truenas-ip` manually
5. Select platform: **Linux**
6. VS Code will connect and install VS Code Server on TrueNAS
7. Wait for connection to complete
### Method 2: Using SSH Targets
1. Click **Remote Explorer** icon in sidebar
2. Under **SSH Targets**, you'll see configured hosts
3. Click **→** (Connect) next to **truenas**
### First Connection
- VS Code will install **VS Code Server** on TrueNAS (~100MB)
- This is a one-time setup
- May take 1-2 minutes
- You'll see progress in bottom right
---
## Step 7: Navigate to Your Stacks Directory
Once connected:
1. **File → Open Folder**
2. Type: `/mnt/tank/stacks`
3. Click **OK**
4. VS Code now shows your stacks directory in explorer!
---
## Step 8: Install Helpful Extensions (Remote)
Once connected to TrueNAS, install these extensions **on the remote**:
### Recommended Extensions
1. **Docker** (`ms-azuretools.vscode-docker`)
- Syntax highlighting for docker-compose files
- Docker commands integration
2. **YAML** (`redhat.vscode-yaml`)
- YAML syntax validation
- Auto-completion
3. **Remote - SSH: Editing Configuration Files** (automatic)
- Edit SSH config directly from VS Code
### Install Extensions on Remote
1. Click **Extensions** icon
2. Search for extension
3. Click **Install in SSH: truenas**
4. Extensions install on the TrueNAS server
---
## Usage Tips
### Open Terminal in VS Code
- **Terminal → New Terminal** (`` Ctrl+` ``)
- Opens bash terminal directly on TrueNAS
- Already in the folder you have open
### Edit docker-compose Files
1. Navigate to `/mnt/tank/stacks/traefik/`
2. Edit `docker-compose.yml`
3. Syntax highlighting and validation included
4. Save with `Ctrl+S`
### Run Docker Commands
```bash
# In VS Code terminal
cd /mnt/tank/stacks/traefik
docker compose up -d
docker logs traefik -f
```
### Multiple Folders
Open workspace with multiple stack directories:
1. **File → Add Folder to Workspace**
2. Add `/mnt/tank/stacks/traefik`
3. Add `/mnt/tank/stacks/gitea`
4. Add `/mnt/tank/stacks/servarr`
5. **File → Save Workspace As**`truenas-stacks.code-workspace`
---
## Troubleshooting
### Connection Refused
```bash
# Check SSH service is running on TrueNAS
# TrueNAS UI → System → Services → SSH → Running
# Test from terminal
ssh admin@truenas-ip
```
### Permission Denied (publickey)
```bash
# Verify public key is added to TrueNAS
# TrueNAS UI → Credentials → Local Users → Edit → SSH Public Key
# Or enable password authentication temporarily
# TrueNAS UI → System → Services → SSH → Edit
# ☑ Allow Password Authentication
```
### VS Code Server Installation Fails
```bash
# SSH into TrueNAS manually
ssh truenas
# Check available disk space
df -h
# VS Code Server needs ~100MB in home directory
# Clear space if needed
```
### "Could not establish connection"
```bash
# Check VS Code settings
# Ctrl+, → Search "remote.SSH.path"
# Should point to ssh executable
# Windows: C:\Windows\System32\OpenSSH\ssh.exe
# WSL: /usr/bin/ssh
```
### Wrong Platform Detected
If VS Code thinks TrueNAS is Windows/Mac:
1. `Ctrl+Shift+P`
2. **Remote-SSH: Settings**
3. Add to `settings.json`:
```json
"remote.SSH.remotePlatform": {
"truenas": "linux"
}
```
---
## Security Best Practices
### Disable Password Authentication (After Key Setup)
Once SSH keys are working:
1. TrueNAS UI → **System → Services → SSH → Edit**
2. ☐ **Allow Password Authentication** (uncheck)
3. ☑ **Login as Root with Password** (uncheck)
4. Click **Save**
Now only SSH key authentication is allowed.
### Use SSH Key Passphrase
When generating keys, add a passphrase:
```bash
ssh-keygen -t ed25519 -C "truenas-access"
# Enter passphrase when prompted
```
Use `ssh-agent` to avoid typing passphrase repeatedly:
```bash
# Start ssh-agent (WSL)
eval "$(ssh-agent -s)"
# Add key
ssh-add ~/.ssh/id_ed25519
# Enter passphrase once
# Key is cached for session
```
### Firewall Considerations
If accessing TrueNAS from outside your network:
- **Don't expose SSH (port 22) directly to internet**
- Use VPN (Tailscale, Wireguard) instead
- Or use SSH tunneling through a bastion host
---
## Quick Reference
### Connect to TrueNAS
```bash
# Command line
ssh truenas
# VS Code
Ctrl+Shift+P → Remote-SSH: Connect to Host → truenas
```
### Common Paths
- **Stacks:** `/mnt/tank/stacks/`
- **Configs:** `/mnt/tank/configs/`
- **Media:** `/mnt/tank/media/`
### Useful VS Code Shortcuts
- **Open Terminal:** `` Ctrl+` ``
- **Command Palette:** `Ctrl+Shift+P`
- **Open Folder:** `Ctrl+K Ctrl+O`
- **Search Files:** `Ctrl+P`
- **Save:** `Ctrl+S`
- **Close Remote:** Click **SSH: truenas** in bottom left → **Close Remote Connection**
---
## Next Steps
- [ ] Install Remote - SSH extension in VS Code
- [ ] Enable SSH service on TrueNAS
- [ ] Generate SSH key on local machine
- [ ] Add public key to TrueNAS
- [ ] Configure ~/.ssh/config with TrueNAS host
- [ ] Test SSH connection from terminal
- [ ] Connect VS Code to TrueNAS
- [ ] Open `/mnt/tank/stacks` folder in VS Code
- [ ] Install Docker and YAML extensions (remote)
- [ ] Disable password authentication (after key setup)
- [ ] Create workspace for multiple stack folders
---
## Resources
- [VS Code Remote - SSH Documentation](https://code.visualstudio.com/docs/remote/ssh)
- [TrueNAS Scale SSH Documentation](https://www.truenas.com/docs/scale/scaletutorials/systemsettings/services/configuringsshservice/)

View File

@@ -0,0 +1,141 @@
services:
gluetun:
image: qmcgaw/gluetun:latest
container_name: gluetun
cap_add:
- NET_ADMIN
environment:
- VPN_SERVICE_PROVIDER=protonvpn
- VPN_TYPE=wireguard
- WIREGUARD_PRIVATE_KEY=${WIREGUARD_PRIVATE_KEY}
- SERVER_COUNTRIES=Netherlands
- TZ=Europe/Amsterdam
volumes:
- /mnt/tank/configs/gluetun:/gluetun
- /mnt/tank/configs/gluetun-tmp:/tmp/gluetun
ports:
- 8080:8080 # qBittorrent WebUI
- 7878:7878 # Radarr
- 8686:8686 # Lidarr
- 8989:8989 # Sonarr
- 9696:9696 # Prowlarr
- 6767:6767 # Bazarr
restart: unless-stopped
qbittorrent:
image: lscr.io/linuxserver/qbittorrent:latest
container_name: qbittorrent
environment:
- PUID=568
- PGID=568
- TZ=Europe/Amsterdam
- WEBUI_PORT=8080
volumes:
- /mnt/tank/configs/qbittorrent:/config
- /mnt/tank/media:/media
network_mode: service:gluetun
depends_on:
- gluetun
restart: unless-stopped
prowlarr:
image: lscr.io/linuxserver/prowlarr:latest
container_name: prowlarr
environment:
- PUID=568
- PGID=568
- TZ=Europe/Amsterdam
volumes:
- /mnt/tank/configs/prowlarr:/config
- /mnt/tank/media:/media
network_mode: service:gluetun
depends_on:
- gluetun
restart: unless-stopped
lidarr:
image: lscr.io/linuxserver/lidarr:latest
container_name: lidarr
environment:
- PUID=568
- PGID=568
- TZ=Europe/Amsterdam
volumes:
- /mnt/tank/configs/lidarr:/config
- /mnt/tank/media:/media
network_mode: service:gluetun
depends_on:
- gluetun
restart: unless-stopped
radarr:
image: lscr.io/linuxserver/radarr:latest
container_name: radarr
environment:
- PUID=568
- PGID=568
- TZ=Europe/Amsterdam
volumes:
- /mnt/tank/configs/radarr:/config
- /mnt/tank/media:/media
network_mode: service:gluetun
depends_on:
- gluetun
restart: unless-stopped
sonarr:
image: lscr.io/linuxserver/sonarr:latest
container_name: sonarr
environment:
- PUID=568
- PGID=568
- TZ=Europe/Amsterdam
volumes:
- /mnt/tank/configs/sonarr:/config
- /mnt/tank/media:/media
network_mode: service:gluetun
depends_on:
- gluetun
restart: unless-stopped
bazarr:
image: lscr.io/linuxserver/bazarr:latest
container_name: bazarr
environment:
- PUID=568
- PGID=568
- TZ=Europe/Amsterdam
volumes:
- /mnt/tank/configs/bazarr:/config
- /mnt/tank/media:/media
network_mode: service:gluetun
depends_on:
- gluetun
- sonarr
- radarr
restart: unless-stopped
recyclarr:
image: ghcr.io/recyclarr/recyclarr:latest
container_name: recyclarr
user: 568:568
environment:
- CRON_SCHEDULE=0 0 * * *
- TZ=Europe/Amsterdam
volumes:
- /mnt/tank/configs/recyclarr:/config
network_mode: service:gluetun
depends_on:
- gluetun
restart: unless-stopped
dozzle:
image: amir20/dozzle:latest
container_name: dozzle
ports:
- 9999:8080 # Access Dozzle UI at http://<host-ip>:9999
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
restart: unless-stopped
watchtower:
image: containrrr/watchtower:latest
container_name: watchtower
volumes:
- /var/run/docker.sock:/var/run/docker.sock
environment:
- TZ=Europe/Amsterdam
- WATCHTOWER_CLEANUP=true
restart: unless-stopped
networks: {}