mirror of
https://github.com/kossakovsky/n8n-install.git
synced 2026-03-07 22:33:11 +00:00
Add Portainer integration as an optional service
- Updated .env.example to include PORTAINER_HOSTNAME, PORTAINER_USERNAME, PORTAINER_PASSWORD, and PORTAINER_PASSWORD_HASH for configuration. - Modified Caddyfile to add a reverse proxy for Portainer with basic authentication. - Enhanced docker-compose.yml to include a new Portainer service and associated volume. - Updated scripts to generate Portainer credentials and include it in the setup wizard and final report. - Documented the integration process and reflections in the memory bank for future reference.
This commit is contained in:
10
.env.example
10
.env.example
@@ -43,6 +43,14 @@ PROMETHEUS_PASSWORD=
|
||||
SEARXNG_USERNAME=
|
||||
SEARXNG_PASSWORD=
|
||||
|
||||
############
|
||||
# [required]
|
||||
# portainer credentials - you set this to whatever you want, just make it a long and secure string for both!
|
||||
############
|
||||
|
||||
PORTAINER_USERNAME=
|
||||
PORTAINER_PASSWORD=
|
||||
|
||||
|
||||
############
|
||||
# [required]
|
||||
@@ -135,6 +143,7 @@ WEAVIATE_HOSTNAME=weaviate.yourdomain.com
|
||||
NEO4J_HOSTNAME=neo4j.yourdomain.com
|
||||
GRAFANA_HOSTNAME=grafana.yourdomain.com
|
||||
PROMETHEUS_HOSTNAME=prometheus.yourdomain.com
|
||||
PORTAINER_HOSTNAME=portainer.yourdomain.com
|
||||
LETTA_HOSTNAME=letta.yourdomain.com
|
||||
QDRANT_HOSTNAME=qdrant.yourdomain.com
|
||||
LETSENCRYPT_EMAIL=
|
||||
@@ -300,3 +309,4 @@ DIFY_EXPOSE_NGINX_SSL_PORT=8443
|
||||
COMPOSE_PROFILES="n8n,flowise,monitoring"
|
||||
PROMETHEUS_PASSWORD_HASH=
|
||||
SEARXNG_PASSWORD_HASH=
|
||||
PORTAINER_PASSWORD_HASH=
|
||||
|
||||
@@ -53,6 +53,14 @@
|
||||
reverse_proxy prometheus:9090
|
||||
}
|
||||
|
||||
# Portainer
|
||||
{$PORTAINER_HOSTNAME} {
|
||||
basic_auth {
|
||||
{$PORTAINER_USERNAME} {$PORTAINER_PASSWORD_HASH}
|
||||
}
|
||||
reverse_proxy portainer:9000
|
||||
}
|
||||
|
||||
# Letta
|
||||
{$LETTA_HOSTNAME} {
|
||||
reverse_proxy letta:8283
|
||||
|
||||
@@ -15,6 +15,7 @@ volumes:
|
||||
prometheus_data:
|
||||
letta_data:
|
||||
weaviate_data:
|
||||
portainer_data:
|
||||
|
||||
x-n8n: &service-n8n
|
||||
build:
|
||||
@@ -212,6 +213,9 @@ services:
|
||||
- PROMETHEUS_PASSWORD_HASH=${PROMETHEUS_PASSWORD_HASH}
|
||||
- SEARXNG_USERNAME=${SEARXNG_USERNAME}
|
||||
- SEARXNG_PASSWORD_HASH=${SEARXNG_PASSWORD_HASH}
|
||||
- PORTAINER_HOSTNAME=${PORTAINER_HOSTNAME}
|
||||
- PORTAINER_USERNAME=${PORTAINER_USERNAME}
|
||||
- PORTAINER_PASSWORD_HASH=${PORTAINER_PASSWORD_HASH}
|
||||
cap_drop:
|
||||
- ALL
|
||||
cap_add:
|
||||
@@ -570,3 +574,12 @@ services:
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
start_period: 10s
|
||||
|
||||
portainer:
|
||||
image: portainer/portainer-ce:latest
|
||||
container_name: portainer
|
||||
profiles: ["portainer"]
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- portainer_data:/data
|
||||
- ${DOCKER_SOCKET_LOCATION:-/var/run/docker.sock}:/var/run/docker.sock
|
||||
|
||||
@@ -3,6 +3,10 @@
|
||||
## Current Phase
|
||||
**READY FOR NEW TASK** - Archive Phase Complete
|
||||
|
||||
### Last Completed Task
|
||||
- Portainer Integration (Level 2) — COMPLETED & ARCHIVED (2025-08-08)
|
||||
- Archive: `memory-bank/archive/feature-portainer-integration_20250808.md`
|
||||
|
||||
## Previous Task
|
||||
**Dify AI Platform Integration** - Level 3 (Intermediate Feature)
|
||||
**Status**: ✅ COMPLETED, REFLECTED, AND ARCHIVED
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
# Archive: Portainer Integration (Level 2)
|
||||
|
||||
- Archive Date: 2025-08-08
|
||||
- Status: COMPLETED & ARCHIVED
|
||||
- Task: Add Portainer Service (Docker Management UI)
|
||||
- Reflection Document: `memory-bank/reflection/reflection-portainer-integration.md`
|
||||
|
||||
## Overview
|
||||
Added Portainer CE as an optional, profile-based service to manage Docker through a secure Caddy reverse proxy with basic authentication.
|
||||
|
||||
## What Changed
|
||||
- `.env.example`: Added `PORTAINER_HOSTNAME`, `PORTAINER_USERNAME`, `PORTAINER_PASSWORD`, `PORTAINER_PASSWORD_HASH`.
|
||||
- `scripts/03_generate_secrets.sh`: Generates `PORTAINER_PASSWORD`, sets `PORTAINER_USERNAME` from email, computes bcrypt `PORTAINER_PASSWORD_HASH` via Caddy.
|
||||
- `scripts/04_wizard.sh`: Added `portainer` to selectable services.
|
||||
- `scripts/06_final_report.sh`: Added Portainer access output.
|
||||
- `Caddyfile`: Added host block with `basic_auth` and `reverse_proxy portainer:9000`.
|
||||
- `docker-compose.yml`: Added `portainer_data` volume, caddy env vars for Portainer, and `portainer` service with Docker socket mount.
|
||||
|
||||
## Access
|
||||
- External: `https://${PORTAINER_HOSTNAME}`
|
||||
- Caddy basic_auth: `${PORTAINER_USERNAME}` / `${PORTAINER_PASSWORD}`
|
||||
- Note: On first login, Portainer prompts for admin setup.
|
||||
|
||||
## Configuration Summary
|
||||
- Caddy:
|
||||
- Host: `{$PORTAINER_HOSTNAME}`
|
||||
- Auth: `basic_auth { {$PORTAINER_USERNAME} {$PORTAINER_PASSWORD_HASH} }`
|
||||
- Upstream: `portainer:9000`
|
||||
- Compose service:
|
||||
- Image: `portainer/portainer-ce:latest`
|
||||
- Profiles: `["portainer"]`
|
||||
- Volumes:
|
||||
- `portainer_data:/data`
|
||||
- `${DOCKER_SOCKET_LOCATION:-/var/run/docker.sock}:/var/run/docker.sock`
|
||||
|
||||
## Env Variables
|
||||
- `PORTAINER_HOSTNAME=portainer.yourdomain.com`
|
||||
- `PORTAINER_USERNAME`
|
||||
- `PORTAINER_PASSWORD`
|
||||
- `PORTAINER_PASSWORD_HASH`
|
||||
|
||||
## Security Notes
|
||||
- External access protected by Caddy `basic_auth`.
|
||||
- Portainer requires admin setup on first login; credentials there are independent of Caddy auth.
|
||||
- Docker socket is mounted read/write; restrict access to the URL and keep `.env` safe.
|
||||
|
||||
## Lessons & References
|
||||
- See reflection: `memory-bank/reflection/reflection-portainer-integration.md` for successes, challenges, and improvements.
|
||||
@@ -1,6 +1,6 @@
|
||||
# n8n-installer Project Progress
|
||||
|
||||
## Current Task: Add Gotenberg Service to n8n-installer
|
||||
## Current Task: —
|
||||
|
||||
### Implementation Progress
|
||||
All major components have been implemented successfully:
|
||||
|
||||
39
memory-bank/reflection/reflection-portainer-integration.md
Normal file
39
memory-bank/reflection/reflection-portainer-integration.md
Normal file
@@ -0,0 +1,39 @@
|
||||
# Reflection: Portainer Integration (Level 2)
|
||||
|
||||
## Review Implementation & Compare to Plan
|
||||
- Implemented Portainer as an optional service using a `portainer` Docker Compose profile.
|
||||
- Added Caddy reverse proxy with `basic_auth` using `PORTAINER_USERNAME` and `PORTAINER_PASSWORD_HASH`.
|
||||
- Extended `.env.example` with `PORTAINER_HOSTNAME`, `PORTAINER_USERNAME`, `PORTAINER_PASSWORD`, `PORTAINER_PASSWORD_HASH`.
|
||||
- Updated `scripts/03_generate_secrets.sh` to generate password, set username from email, and bcrypt-hash the password via Caddy.
|
||||
- Added Portainer to `scripts/04_wizard.sh` for selectable installation.
|
||||
- Added access details to `scripts/06_final_report.sh`.
|
||||
- Validated `docker-compose.yml` with `docker compose config -q` and fixed default for `DOCKER_SOCKET_LOCATION`.
|
||||
|
||||
## Successes
|
||||
- Pattern reuse from Prometheus/SearXNG for Caddy `basic_auth` and hash generation.
|
||||
- Clean, minimal changes across existing integration points (env, wizard, report, proxy, compose).
|
||||
- Compose validation passed; good developer UX with sensible defaults.
|
||||
|
||||
## Challenges
|
||||
- Initial compose validation failed due to empty `DOCKER_SOCKET_LOCATION` causing an invalid volume spec.
|
||||
- Ensured default fallback `:/var/run/docker.sock` to avoid requiring `.env` at validation time.
|
||||
|
||||
## Lessons Learned
|
||||
- Provide sane defaults for host-mounted paths referenced via environment variables to keep validation/dev flows smooth.
|
||||
- Align new service auth with existing patterns to minimize cognitive load and security inconsistencies.
|
||||
|
||||
## Process/Technical Improvements
|
||||
- Consider centralizing the basic auth hashing routine to avoid duplication across services.
|
||||
- Optionally prompt for enabling Portainer in the secrets script to improve onboarding flow.
|
||||
|
||||
## Verification Checklist
|
||||
- Implementation thoroughly reviewed: YES
|
||||
- Successes documented: YES
|
||||
- Challenges documented: YES
|
||||
- Lessons Learned documented: YES
|
||||
- Process/Technical Improvements identified: YES
|
||||
- reflection.md created: YES (this document)
|
||||
- tasks.md updated with reflection status: YES (to be updated)
|
||||
|
||||
## Final Notes
|
||||
- First login still requires Portainer admin setup; Caddy `basic_auth` adds an external protection layer consistent with project norms.
|
||||
@@ -385,4 +385,84 @@ Ready to archive the completed Dify integration task and prepare for next develo
|
||||
→ **Memory Bank is ready for the next task**
|
||||
→ **To start a new task, use VAN MODE**
|
||||
|
||||
**Final Task Status**: <EFBFBD><EFBFBD> SUCCESSFULLY COMPLETED, REFLECTED, AND ARCHIVED
|
||||
**Final Task Status**: ✅ SUCCESSFULLY COMPLETED, REFLECTED, AND ARCHIVED
|
||||
|
||||
## New Task: Add Portainer Service (Docker Management UI)
|
||||
|
||||
### Description
|
||||
Integrate Portainer Community Edition as an optional service to manage the local Docker environment through a secure, Caddy-proxied hostname with basic authentication.
|
||||
|
||||
### Complexity
|
||||
- Level: 2 (Simple Enhancement)
|
||||
- Type: Add-on service integration using existing patterns (profiles, Caddy, env generation, wizard, final report)
|
||||
|
||||
### Overview of Changes
|
||||
- Add Portainer as a new Docker Compose service behind profile `portainer`.
|
||||
- Expose via Caddy at `PORTAINER_HOSTNAME`, protected with Caddy `basic_auth`.
|
||||
- Generate `PORTAINER_PASSWORD` with bcrypt hash `PORTAINER_PASSWORD_HASH`. Use `PORTAINER_USERNAME` (from user email) for convenience.
|
||||
- Add service to wizard for optional selection.
|
||||
- Include access details in final report.
|
||||
|
||||
### Files to Modify
|
||||
- `scripts/03_generate_secrets.sh`
|
||||
- Generate: `PORTAINER_PASSWORD` (random), username from email `PORTAINER_USERNAME`.
|
||||
- Compute bcrypt `PORTAINER_PASSWORD_HASH` via `caddy hash-password`.
|
||||
- Persist hash in `.env` like with Prometheus/SearXNG.
|
||||
- `scripts/04_wizard.sh`
|
||||
- Add service option: `portainer` "Portainer (Docker management UI)".
|
||||
- `scripts/06_final_report.sh`
|
||||
- Add section for Portainer host, username, and password.
|
||||
- `.env.example`
|
||||
- Add variables: `PORTAINER_HOSTNAME`, `PORTAINER_USERNAME`, `PORTAINER_PASSWORD`, `PORTAINER_PASSWORD_HASH`.
|
||||
- `Caddyfile`
|
||||
- Add host block for `{$PORTAINER_HOSTNAME}` with `basic_auth` using `PORTAINER_USERNAME`/`PORTAINER_PASSWORD_HASH`, proxy to `portainer:9000`.
|
||||
- `docker-compose.yml`
|
||||
- Add `portainer` service (`profiles: ["portainer"]`), volumes: `portainer_data` and `${DOCKER_SOCKET_LOCATION}:/var/run/docker.sock`.
|
||||
- Add `portainer_data` to top-level `volumes`.
|
||||
- Pass Portainer env/host variables into `caddy` service environment: `PORTAINER_HOSTNAME`, `PORTAINER_USERNAME`, `PORTAINER_PASSWORD_HASH`.
|
||||
|
||||
### Implementation Steps
|
||||
1) `.env.example`
|
||||
- Insert under hostnames: `PORTAINER_HOSTNAME=portainer.yourdomain.com`.
|
||||
- Insert credentials: `PORTAINER_USERNAME=`, `PORTAINER_PASSWORD=`.
|
||||
- Insert hash section end: `PORTAINER_PASSWORD_HASH=`.
|
||||
2) `scripts/03_generate_secrets.sh`
|
||||
- Add to `VARS_TO_GENERATE`: `"PORTAINER_PASSWORD"="password:32"`.
|
||||
- Set `generated_values["PORTAINER_USERNAME"]="$USER_EMAIL"`.
|
||||
- Add `found_vars["PORTAINER_USERNAME"]=0`, include in `user_input_vars` and in the post-template append list.
|
||||
- Compute hash with caddy (mirror Prometheus/SearXNG pattern) and `_update_or_add_env_var "PORTAINER_PASSWORD_HASH"`.
|
||||
3) `scripts/04_wizard.sh`
|
||||
- Add to `base_services_data`: `"portainer" "Portainer (Docker management UI)"`.
|
||||
4) `scripts/06_final_report.sh`
|
||||
- Add a block gated by `is_profile_active "portainer"` printing host, user, password.
|
||||
5) `Caddyfile`
|
||||
- Add block for `{$PORTAINER_HOSTNAME}` with `basic_auth { {$PORTAINER_USERNAME} {$PORTAINER_PASSWORD_HASH} }` and `reverse_proxy portainer:9000`.
|
||||
6) `docker-compose.yml`
|
||||
- Add `portainer_data:` volume.
|
||||
- Add `portainer` service using `portainer/portainer-ce:latest`, `restart: unless-stopped`, `profiles: ["portainer"]`, volumes mapping `portainer_data:/data` and `${DOCKER_SOCKET_LOCATION}:/var/run/docker.sock`.
|
||||
- Add `PORTAINER_*` variables to the `caddy` service environment section.
|
||||
|
||||
### Potential Challenges
|
||||
- Portainer first-run setup: even with Caddy `basic_auth`, Portainer will request initial admin setup on first login. This is expected; Caddy auth protects the external URL.
|
||||
- Docker socket mount must match host path via `${DOCKER_SOCKET_LOCATION}`.
|
||||
|
||||
### Testing Strategy
|
||||
- Generate/update `.env` with `03_generate_secrets.sh` and choose `portainer` in `04_wizard.sh`.
|
||||
- Start: `docker compose up -d caddy portainer`.
|
||||
- Verify `https://PORTAINER_HOSTNAME` prompts for Caddy basic auth, then complete Portainer admin onboarding.
|
||||
|
||||
### Next Mode Recommendation
|
||||
- Implement Mode (no creative phase required).
|
||||
|
||||
### Reflection Status (Portainer)
|
||||
- [x] Implementation thoroughly reviewed
|
||||
- [x] Successes documented
|
||||
- [x] Challenges and solutions analyzed
|
||||
- [x] Lessons Learned documented
|
||||
- [x] Process/Technical improvements identified
|
||||
- [x] reflection-portainer-integration.md created
|
||||
- [x] tasks.md updated with reflection status
|
||||
|
||||
### Archiving Status (Portainer)
|
||||
- [x] Archive document created: `memory-bank/archive/feature-portainer-integration_20250808.md`
|
||||
- [x] tasks.md marked COMPLETE for Portainer
|
||||
|
||||
@@ -41,6 +41,7 @@ declare -A VARS_TO_GENERATE=(
|
||||
["LOGFLARE_PUBLIC_ACCESS_TOKEN"]="fixed:not-in-use" # For supabase-vector, can't be empty
|
||||
["PROMETHEUS_PASSWORD"]="password:32" # Added Prometheus password
|
||||
["SEARXNG_PASSWORD"]="password:32" # Added SearXNG admin password
|
||||
["PORTAINER_PASSWORD"]="password:32" # Added Portainer password for Caddy basic_auth
|
||||
["LETTA_SERVER_PASSWORD"]="password:32" # Added Letta server password
|
||||
["LANGFUSE_INIT_USER_PASSWORD"]="password:32"
|
||||
["LANGFUSE_INIT_PROJECT_PUBLIC_KEY"]="langfuse_pk:32"
|
||||
@@ -368,6 +369,7 @@ generated_values["SEARXNG_USERNAME"]="$USER_EMAIL"
|
||||
generated_values["LANGFUSE_INIT_USER_EMAIL"]="$USER_EMAIL"
|
||||
generated_values["N8N_WORKER_COUNT"]="$N8N_WORKER_COUNT"
|
||||
generated_values["WEAVIATE_USERNAME"]="$USER_EMAIL" # Set Weaviate username for Caddy
|
||||
generated_values["PORTAINER_USERNAME"]="$USER_EMAIL" # Set Portainer username for Caddy
|
||||
|
||||
if [[ -n "$OPENAI_API_KEY" ]]; then
|
||||
generated_values["OPENAI_API_KEY"]="$OPENAI_API_KEY"
|
||||
@@ -391,6 +393,7 @@ found_vars["LANGFUSE_INIT_USER_EMAIL"]=0
|
||||
found_vars["N8N_WORKER_COUNT"]=0
|
||||
found_vars["WEAVIATE_USERNAME"]=0
|
||||
found_vars["NEO4J_AUTH_USERNAME"]=0
|
||||
found_vars["PORTAINER_USERNAME"]=0
|
||||
|
||||
# Read template, substitute domain, generate initial values
|
||||
while IFS= read -r line || [[ -n "$line" ]]; do
|
||||
@@ -437,7 +440,7 @@ while IFS= read -r line || [[ -n "$line" ]]; do
|
||||
# This 'else' block is for lines from template not covered by existing values or VARS_TO_GENERATE.
|
||||
# Check if it is one of the user input vars - these are handled by found_vars later if not in template.
|
||||
is_user_input_var=0 # Reset for each line
|
||||
user_input_vars=("FLOWISE_USERNAME" "DASHBOARD_USERNAME" "LETSENCRYPT_EMAIL" "RUN_N8N_IMPORT" "PROMETHEUS_USERNAME" "SEARXNG_USERNAME" "OPENAI_API_KEY" "LANGFUSE_INIT_USER_EMAIL" "N8N_WORKER_COUNT" "WEAVIATE_USERNAME" "NEO4J_AUTH_USERNAME")
|
||||
user_input_vars=("FLOWISE_USERNAME" "DASHBOARD_USERNAME" "LETSENCRYPT_EMAIL" "RUN_N8N_IMPORT" "PROMETHEUS_USERNAME" "SEARXNG_USERNAME" "OPENAI_API_KEY" "LANGFUSE_INIT_USER_EMAIL" "N8N_WORKER_COUNT" "WEAVIATE_USERNAME" "NEO4J_AUTH_USERNAME" "PORTAINER_USERNAME")
|
||||
for uivar in "${user_input_vars[@]}"; do
|
||||
if [[ "$varName" == "$uivar" ]]; then
|
||||
is_user_input_var=1
|
||||
@@ -520,7 +523,7 @@ if [[ -z "${generated_values[SERVICE_ROLE_KEY]}" ]]; then
|
||||
fi
|
||||
|
||||
# Add any custom variables that weren't found in the template
|
||||
for var in "FLOWISE_USERNAME" "DASHBOARD_USERNAME" "LETSENCRYPT_EMAIL" "RUN_N8N_IMPORT" "OPENAI_API_KEY" "PROMETHEUS_USERNAME" "SEARXNG_USERNAME" "LANGFUSE_INIT_USER_EMAIL" "N8N_WORKER_COUNT" "WEAVIATE_USERNAME" "NEO4J_AUTH_USERNAME"; do
|
||||
for var in "FLOWISE_USERNAME" "DASHBOARD_USERNAME" "LETSENCRYPT_EMAIL" "RUN_N8N_IMPORT" "OPENAI_API_KEY" "PROMETHEUS_USERNAME" "SEARXNG_USERNAME" "LANGFUSE_INIT_USER_EMAIL" "N8N_WORKER_COUNT" "WEAVIATE_USERNAME" "NEO4J_AUTH_USERNAME" "PORTAINER_USERNAME"; do
|
||||
if [[ ${found_vars["$var"]} -eq 0 && -v generated_values["$var"] ]]; then
|
||||
# Before appending, check if it's already in TMP_ENV_FILE to avoid duplicates
|
||||
if ! grep -q -E "^${var}=" "$TMP_ENV_FILE"; then
|
||||
@@ -631,6 +634,19 @@ if [[ -z "$FINAL_SEARXNG_HASH" && -n "$SEARXNG_PLAIN_PASS" ]]; then
|
||||
fi
|
||||
_update_or_add_env_var "SEARXNG_PASSWORD_HASH" "$FINAL_SEARXNG_HASH"
|
||||
|
||||
# --- PORTAINER ---
|
||||
PORTAINER_PLAIN_PASS="${generated_values["PORTAINER_PASSWORD"]}"
|
||||
FINAL_PORTAINER_HASH="${generated_values[PORTAINER_PASSWORD_HASH]}"
|
||||
|
||||
if [[ -z "$FINAL_PORTAINER_HASH" && -n "$PORTAINER_PLAIN_PASS" ]]; then
|
||||
NEW_HASH=$(_generate_and_get_hash "$PORTAINER_PLAIN_PASS")
|
||||
if [[ -n "$NEW_HASH" ]]; then
|
||||
FINAL_PORTAINER_HASH="$NEW_HASH"
|
||||
generated_values["PORTAINER_PASSWORD_HASH"]="$NEW_HASH"
|
||||
fi
|
||||
fi
|
||||
_update_or_add_env_var "PORTAINER_PASSWORD_HASH" "$FINAL_PORTAINER_HASH"
|
||||
|
||||
|
||||
if [ $? -eq 0 ]; then # This $? reflects the status of the last mv command from the last _update_or_add_env_var call.
|
||||
# For now, assuming if we reached here and mv was fine, primary operations were okay.
|
||||
|
||||
@@ -54,16 +54,17 @@ base_services_data=(
|
||||
"dify" "Dify (AI Application Development Platform with LLMOps)"
|
||||
"flowise" "Flowise (AI Agent Builder)"
|
||||
"monitoring" "Monitoring Suite (Prometheus, Grafana, cAdvisor, Node-Exporter)"
|
||||
"portainer" "Portainer (Docker management UI)"
|
||||
"langfuse" "Langfuse Suite (AI Observability - includes Clickhouse, Minio)"
|
||||
"qdrant" "Qdrant (Vector Database)"
|
||||
"supabase" "Supabase (Backend as a Service)"
|
||||
"weaviate" "Weaviate (Vector Database with API Key Auth)"
|
||||
"neo4j" "Neo4j (Graph Database)"
|
||||
"open-webui" "Open WebUI (ChatGPT-like Interface)"
|
||||
"searxng" "SearXNG (Private Metasearch Engine)"
|
||||
"crawl4ai" "Crawl4ai (Web Crawler for AI)"
|
||||
"letta" "Letta (Agent Server & SDK)"
|
||||
"gotenberg" "Gotenberg (Document Conversion API)"
|
||||
"crawl4ai" "Crawl4ai (Web Crawler for AI)"
|
||||
"open-webui" "Open WebUI (ChatGPT-like Interface)"
|
||||
"searxng" "SearXNG (Private Metasearch Engine)"
|
||||
"ollama" "Ollama (Local LLM Runner - select hardware in next step)"
|
||||
)
|
||||
|
||||
|
||||
@@ -127,6 +127,16 @@ if is_profile_active "searxng"; then
|
||||
echo "Password: ${SEARXNG_PASSWORD:-<not_set_in_env>}"
|
||||
fi
|
||||
|
||||
if is_profile_active "portainer"; then
|
||||
echo
|
||||
echo "================================= Portainer ==========================="
|
||||
echo
|
||||
echo "Host: ${PORTAINER_HOSTNAME:-<hostname_not_set>}"
|
||||
echo "User: ${PORTAINER_USERNAME:-<not_set_in_env>}"
|
||||
echo "Password: ${PORTAINER_PASSWORD:-<not_set_in_env>}"
|
||||
echo "(Note: On first login, Portainer will prompt to set up an admin user.)"
|
||||
fi
|
||||
|
||||
if is_profile_active "qdrant"; then
|
||||
echo
|
||||
echo "================================= Qdrant =============================="
|
||||
|
||||
Reference in New Issue
Block a user