9.1 KiB
9.1 KiB
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.eudomain - TrueNAS Scale running Nextcloud
Step 1: Prepare Git Repository
On your local machine (where you created the files):
# 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 secretssecrets/directory- Any
*.logfiles - Backup files
Step 2: Generate Secrets
Before deploying, generate the Authelia secrets:
Option A: On Windows (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
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:
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:
# 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:
- Apps → Installed → Nextcloud → Edit
- Environment Variables:
(Replace 192.168.1.50 with your Proxmox VM IP)NEXTCLOUD_TRUSTED_DOMAINS=cloud.lemonlink.eu OVERWRITEPROTOCOL=https OVERWRITEHOST=cloud.lemonlink.eu OVERWRITECLIURL=https://cloud.lemonlink.eu TRUSTED_PROXIES=192.168.1.50 - Save
5. Configure Cloudflare DNS
- Login to Cloudflare Dashboard
- 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 |
- SSL/TLS → Overview:
- Set to Full (strict)
- Enable Always Use HTTPS
Step 5: Verify Everything Works
Test Commands
# 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:
- Generate password hash:
docker run --rm authelia/authelia:latest authelia crypto hash generate argon2 --password 'FamilyPassword123!'
- Edit
authelia/users_database.ymlin your Git repo - Push changes
- In Portainer: Stacks → lemonsec → Pull and redeploy
Updating the Stack
Update from Git (new commits)
- Stacks → lemonsec
- Click Pull and redeploy
- Portainer pulls latest changes and restarts
Update container images
- Stacks → lemonsec → Editor
- Click Update the stack (this pulls new images)
Or manually:
# 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_IPandTRUENAS_NEXTCLOUD_PORTare correct - Test:
curl http://TRUENAS_IP:TRUENAS_NEXTCLOUD_PORTfrom Proxmox VM
SSL Certificate issues
- Check Cloudflare API credentials
- Verify DNS records exist
- Check Traefik logs in Portainer
CrowdSec not blocking
- Verify
CROWDSEC_API_KEYis 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/LemonSecfrom 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
# 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
- ✅ Verify Nextcloud is accessible
- ✅ Test family member logins
- ✅ Set up mobile apps
- ✅ Enable monitoring (optional)
- ✅ 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