300 lines
9.1 KiB
Markdown
300 lines
9.1 KiB
Markdown
# Deploy LemonSec via Portainer Git Repository
|
|
|
|
## Overview
|
|
|
|
This guide shows how to deploy LemonSec using Portainer's **Git Repository** feature. This is the cleanest deployment method - no manual file copying, just point Portainer to your Git repo!
|
|
|
|
## Prerequisites
|
|
|
|
- [ ] Portainer installed on Proxmox VM
|
|
- [ ] Git repository at `https://git.lemonlink.eu/impulsivefps/LemonSec`
|
|
- [ ] Cloudflare account with `lemonlink.eu` domain
|
|
- [ ] TrueNAS Scale running Nextcloud
|
|
|
|
## Step 1: Prepare Git Repository
|
|
|
|
### On your local machine (where you created the files):
|
|
|
|
```bash
|
|
# Initialize git repo (if not already)
|
|
cd LemonSec
|
|
git init
|
|
git remote add origin https://git.lemonlink.eu/impulsivefps/LemonSec.git
|
|
|
|
# Add all files
|
|
git add .
|
|
git commit -m "Initial LemonSec deployment"
|
|
|
|
# Push to your Git server
|
|
git push -u origin main
|
|
# or git push -u origin master
|
|
```
|
|
|
|
### Files that should be in the repo:
|
|
```
|
|
LemonSec/
|
|
├── docker-compose.yml ✅ Main stack
|
|
├── stack.env ✅ Environment template
|
|
├── traefik/
|
|
│ ├── traefik.yml ✅ Static config
|
|
│ └── dynamic/
|
|
│ ├── middlewares.yml ✅ Security middlewares
|
|
│ └── tls.yml ✅ TLS settings
|
|
├── authelia/
|
|
│ ├── configuration.yml ✅ Authelia config
|
|
│ └── users_database.yml ✅ Family users
|
|
├── crowdsec/
|
|
│ └── acquis.yaml ✅ Log sources
|
|
└── docs/ ✅ Documentation
|
|
```
|
|
|
|
### Files to NOT commit (already in .gitignore):
|
|
- `.env` - Contains secrets
|
|
- `secrets/` directory
|
|
- Any `*.log` files
|
|
- Backup files
|
|
|
|
## Step 2: Generate Secrets
|
|
|
|
Before deploying, generate the Authelia secrets:
|
|
|
|
### Option A: On Windows (PowerShell)
|
|
```powershell
|
|
$jwt = -join ((1..32) | ForEach-Object { '{0:x2}' -f (Get-Random -Max 256) })
|
|
Write-Host "AUTHELIA_JWT_SECRET: $jwt"
|
|
|
|
$session = -join ((1..32) | ForEach-Object { '{0:x2}' -f (Get-Random -Max 256) })
|
|
Write-Host "AUTHELIA_SESSION_SECRET: $session"
|
|
|
|
$storage = -join ((1..32) | ForEach-Object { '{0:x2}' -f (Get-Random -Max 256) })
|
|
Write-Host "AUTHELIA_STORAGE_KEY: $storage"
|
|
```
|
|
|
|
### Option B: On Linux/macOS
|
|
```bash
|
|
openssl rand -hex 32 # Run 3 times for each secret
|
|
echo "AUTHELIA_JWT_SECRET: $(openssl rand -hex 32)"
|
|
echo "AUTHELIA_SESSION_SECRET: $(openssl rand -hex 32)"
|
|
echo "AUTHELIA_STORAGE_KEY: $(openssl rand -hex 32)"
|
|
```
|
|
|
|
### Option C: In Portainer (after first failed deploy)
|
|
The stack will fail to start without secrets. You can generate them inside the Portainer host:
|
|
```bash
|
|
docker run --rm authelia/authelia:latest authelia crypto rand --length 64 --hex
|
|
docker run --rm alpine openssl rand -hex 32
|
|
```
|
|
|
|
**Save these 3 secrets!** You'll need them in Step 4.
|
|
|
|
## Step 3: Deploy in Portainer
|
|
|
|
### 1. Open Portainer
|
|
Navigate to your Portainer UI: `http://your-proxmox-vm:9000`
|
|
|
|
### 2. Create Stack from Git
|
|
- Click **Stacks** → **Add Stack**
|
|
- Select **Repository** (not Web editor)
|
|
- Fill in:
|
|
|
|
| Field | Value |
|
|
|-------|-------|
|
|
| **Name** | `lemonsec` |
|
|
| **Repository URL** | `https://git.lemonlink.eu/impulsivefps/LemonSec` |
|
|
| **Repository Reference** | `refs/heads/main` (or `refs/heads/master`) |
|
|
| **Compose Path** | `docker-compose.yml` |
|
|
| **Authentication** | (only if repo is private) |
|
|
|
|
### 3. Environment Variables
|
|
Click **Load variables from .env file** or enter manually:
|
|
|
|
**Required Variables:**
|
|
|
|
| Variable | Example Value | Description |
|
|
|----------|---------------|-------------|
|
|
| `CF_API_EMAIL` | `youremail@example.com` | Cloudflare account email |
|
|
| `CF_API_KEY` | `your-cloudflare-global-api-key` | From Cloudflare profile |
|
|
| `TRUENAS_IP` | `192.168.1.100` | TrueNAS Scale VM IP |
|
|
| `TRUENAS_NEXTCLOUD_PORT` | `9001` | Nextcloud port on TrueNAS |
|
|
| `AUTHELIA_JWT_SECRET` | `a1b2c3d4...` (64 hex chars) | Generated secret |
|
|
| `AUTHELIA_SESSION_SECRET` | `e5f6g7h8...` (64 hex chars) | Generated secret |
|
|
| `AUTHELIA_STORAGE_KEY` | `i9j0k1l2...` (64 hex chars) | Generated secret |
|
|
|
|
**Optional Variables:**
|
|
|
|
| Variable | Default | Description |
|
|
|----------|---------|-------------|
|
|
| `TZ` | `Europe/Stockholm` | Timezone |
|
|
| `TAILSCALE_IP` | (empty) | For internal access |
|
|
| `CROWDSEC_API_KEY` | (empty) | Add after first deploy |
|
|
|
|
### 4. Deploy the Stack
|
|
- Click **Deploy the stack**
|
|
- Portainer will pull from Git and start containers
|
|
|
|
## Step 4: Initial Configuration
|
|
|
|
### 1. Check Deployment Status
|
|
In Portainer:
|
|
- **Stacks** → **lemonsec** → Check all containers are running
|
|
- Click on individual containers to view logs
|
|
|
|
### 2. Generate CrowdSec API Key
|
|
Once CrowdSec is running:
|
|
```bash
|
|
# In Portainer → Containers → crowdsec → Console
|
|
# Or SSH to host:
|
|
docker exec crowdsec cscli bouncers add traefik-bouncer
|
|
|
|
# Copy the API key output
|
|
```
|
|
|
|
### 3. Update Environment Variables
|
|
- **Stacks** → **lemonsec** → **Editor** tab
|
|
- Add `CROWDSEC_API_KEY=your-key-here`
|
|
- Click **Update the stack**
|
|
|
|
### 4. Configure TrueNAS Nextcloud
|
|
In TrueNAS Scale:
|
|
1. **Apps** → **Installed** → **Nextcloud** → **Edit**
|
|
2. **Environment Variables**:
|
|
```
|
|
NEXTCLOUD_TRUSTED_DOMAINS=cloud.lemonlink.eu
|
|
OVERWRITEPROTOCOL=https
|
|
OVERWRITEHOST=cloud.lemonlink.eu
|
|
OVERWRITECLIURL=https://cloud.lemonlink.eu
|
|
TRUSTED_PROXIES=192.168.1.50
|
|
```
|
|
(Replace 192.168.1.50 with your Proxmox VM IP)
|
|
3. **Save**
|
|
|
|
### 5. Configure Cloudflare DNS
|
|
1. Login to [Cloudflare Dashboard](https://dash.cloudflare.com)
|
|
2. Add DNS records:
|
|
|
|
| Type | Name | Target | Proxy |
|
|
|------|------|--------|-------|
|
|
| A | cloud | YOUR_PUBLIC_IP | 🟠 Proxied |
|
|
| A | auth | YOUR_PUBLIC_IP | 🟠 Proxied |
|
|
| A | *.local | YOUR_PUBLIC_IP | 🟠 Proxied |
|
|
|
|
3. **SSL/TLS** → **Overview**:
|
|
- Set to **Full (strict)**
|
|
- Enable **Always Use HTTPS**
|
|
|
|
## Step 5: Verify Everything Works
|
|
|
|
### Test Commands
|
|
```bash
|
|
# From any machine:
|
|
curl -I https://cloud.lemonlink.eu
|
|
# Expected: HTTP/2 200 or redirect to login
|
|
|
|
# Check Traefik dashboard (via Tailscale):
|
|
curl -k -I https://traefik.local.lemonlink.eu:8443
|
|
|
|
# Verify SSL certificate:
|
|
echo | openssl s_client -servername cloud.lemonlink.eu -connect cloud.lemonlink.eu:443 2>/dev/null | openssl x509 -noout -dates
|
|
```
|
|
|
|
### Web Access
|
|
- **Nextcloud**: `https://cloud.lemonlink.eu` ✅
|
|
- **Authelia**: `https://auth.lemonlink.eu` ✅
|
|
|
|
## Step 6: Add Family to Authelia (Optional)
|
|
|
|
If you enabled Authelia on Nextcloud:
|
|
|
|
1. Generate password hash:
|
|
```bash
|
|
docker run --rm authelia/authelia:latest authelia crypto hash generate argon2 --password 'FamilyPassword123!'
|
|
```
|
|
|
|
2. Edit `authelia/users_database.yml` in your Git repo
|
|
3. Push changes
|
|
4. In Portainer: **Stacks** → **lemonsec** → **Pull and redeploy**
|
|
|
|
## Updating the Stack
|
|
|
|
### Update from Git (new commits)
|
|
1. **Stacks** → **lemonsec**
|
|
2. Click **Pull and redeploy**
|
|
3. Portainer pulls latest changes and restarts
|
|
|
|
### Update container images
|
|
1. **Stacks** → **lemonsec** → **Editor**
|
|
2. Click **Update the stack** (this pulls new images)
|
|
|
|
Or manually:
|
|
```bash
|
|
# SSH to host
|
|
docker-compose -f /var/lib/docker/volumes/portainer_data/_data/compose/lemonsec/docker-compose.yml pull
|
|
docker-compose -f /var/lib/docker/volumes/portainer_data/_data/compose/lemonsec/docker-compose.yml up -d
|
|
```
|
|
|
|
## Troubleshooting
|
|
|
|
### "CF_API_EMAIL not set" error
|
|
- Check all required environment variables are filled in Portainer
|
|
- Redeploy the stack
|
|
|
|
### "Bad Gateway" for Nextcloud
|
|
- Verify `TRUENAS_IP` and `TRUENAS_NEXTCLOUD_PORT` are correct
|
|
- Test: `curl http://TRUENAS_IP:TRUENAS_NEXTCLOUD_PORT` from Proxmox VM
|
|
|
|
### SSL Certificate issues
|
|
- Check Cloudflare API credentials
|
|
- Verify DNS records exist
|
|
- Check Traefik logs in Portainer
|
|
|
|
### CrowdSec not blocking
|
|
- Verify `CROWDSEC_API_KEY` is set and correct
|
|
- Check CrowdSec logs for connection errors
|
|
|
|
### Can't pull from Git
|
|
- Verify Git URL is accessible from Portainer host
|
|
- Check if repository requires authentication
|
|
- Try: `git ls-remote https://git.lemonlink.eu/impulsivefps/LemonSec` from host
|
|
|
|
## Portainer Stack vs Docker Compose
|
|
|
|
| Feature | Portainer Stacks | Docker Compose CLI |
|
|
|---------|------------------|-------------------|
|
|
| Deployment | Git/Web UI | Command line |
|
|
| Updates | One-click pull | Manual git pull |
|
|
| Environment | UI variables | .env file |
|
|
| Logs | Built-in UI | docker logs |
|
|
| Access control | Portainer RBAC | OS level |
|
|
|
|
## Backup Strategy
|
|
|
|
### Portainer Backup
|
|
Portainer automatically stores stack files in:
|
|
```
|
|
/var/lib/docker/volumes/portainer_data/_data/compose/
|
|
```
|
|
|
|
### Manual Backup
|
|
```bash
|
|
# Backup Portainer data
|
|
docker run --rm -v portainer_data:/data -v $(pwd):/backup alpine tar czf /backup/portainer-backup.tar.gz -C /data .
|
|
|
|
# Backup LemonSec volumes
|
|
docker volume ls | grep lemonsec
|
|
docker run --rm -v lemonsec_traefik-certs:/certs -v $(pwd):/backup alpine tar czf /backup/traefik-certs.tar.gz -C /certs .
|
|
```
|
|
|
|
## Next Steps
|
|
|
|
1. ✅ Verify Nextcloud is accessible
|
|
2. ✅ Test family member logins
|
|
3. ✅ Set up mobile apps
|
|
4. ✅ Enable monitoring (optional)
|
|
5. ✅ Add more services (Vaultwarden, etc.)
|
|
|
|
## Support
|
|
|
|
- **Traefik issues**: Check logs in Portainer → Containers → traefik → Logs
|
|
- **Authelia issues**: Check logs in Portainer → Containers → authelia → Logs
|
|
- **TrueNAS issues**: Check TrueNAS → Apps → Nextcloud → Logs
|