LemonSec/PORTAINER-DEPLOY.md

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.eu domain
  • 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 secrets
  • secrets/ directory
  • Any *.log files
  • 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 StacksAdd 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:

  • Stackslemonsec → 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

  • StackslemonsecEditor tab
  • Add CROWDSEC_API_KEY=your-key-here
  • Click Update the stack

4. Configure TrueNAS Nextcloud

In TrueNAS Scale:

  1. AppsInstalledNextcloudEdit
  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
  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
  1. SSL/TLSOverview:
    • 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:

  1. Generate password hash:
docker run --rm authelia/authelia:latest authelia crypto hash generate argon2 --password 'FamilyPassword123!'
  1. Edit authelia/users_database.yml in your Git repo
  2. Push changes
  3. In Portainer: StackslemonsecPull and redeploy

Updating the Stack

Update from Git (new commits)

  1. Stackslemonsec
  2. Click Pull and redeploy
  3. Portainer pulls latest changes and restarts

Update container images

  1. StackslemonsecEditor
  2. 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_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

# 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