# 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