Updates to online workflow (moved cloudflare back to system service), full rework of homepage, updated a bunch of stuff in general
This commit is contained in:
parent
5a7d38ec71
commit
c658f4bd00
254
config.sh
254
config.sh
@ -25,6 +25,7 @@ TUNNEL_CONFIG_DIR="$SCRIPT_DIR/configs/cloudflare"
|
||||
TUNNEL_CONFIG_FILE="$TUNNEL_CONFIG_DIR/tunnel-config.yml"
|
||||
SERVICES_YAML="$SCRIPT_DIR/configs/homepage/services.yaml"
|
||||
MAIN_HTML="$SCRIPT_DIR/mkdocs/docs/overrides/main.html"
|
||||
MAP_ENV_FILE="$SCRIPT_DIR/map/.env" # Add the map's .env file path
|
||||
|
||||
echo "Looking for .env file at: $ENV_FILE"
|
||||
|
||||
@ -180,6 +181,8 @@ initialize_available_ports() {
|
||||
["HOMEPAGE_PORT"]=3010
|
||||
["GITEA_WEB_PORT"]=3030
|
||||
["GITEA_SSH_PORT"]=2222
|
||||
["MAP_PORT"]=3000
|
||||
["MINI_QR_PORT"]=8089
|
||||
)
|
||||
|
||||
# Find available ports for each service
|
||||
@ -243,6 +246,8 @@ NOCODB_PORT=${NOCODB_PORT:-8090}
|
||||
HOMEPAGE_PORT=${HOMEPAGE_PORT:-3010}
|
||||
GITEA_WEB_PORT=${GITEA_WEB_PORT:-3030}
|
||||
GITEA_SSH_PORT=${GITEA_SSH_PORT:-2222}
|
||||
MAP_PORT=${MAP_PORT:-3000}
|
||||
MINI_QR_PORT=${MINI_QR_PORT:-8089}
|
||||
|
||||
# Domain Configuration
|
||||
BASE_DOMAIN=https://changeme.org
|
||||
@ -251,12 +256,18 @@ LISTMONK_HOSTNAME=listmonk.changeme.org
|
||||
N8N_HOST=n8n.changeme.org
|
||||
GITEA_DOMAIN=git.changeme.org
|
||||
GITEA_ROOT_URL=https://git.changeme.org
|
||||
HOMEPAGE_VAR_BASE_URL=https://changeme.org
|
||||
|
||||
# Cookie and CORS Configuration
|
||||
COOKIE_DOMAIN=.changeme.org
|
||||
ALLOWED_ORIGINS=https://map.changeme.org,http://localhost:3000
|
||||
|
||||
# Cloudflare Configuration
|
||||
CF_API_TOKEN=your_cloudflare_api_token
|
||||
CF_ZONE_ID=your_cloudflare_zone_id
|
||||
CF_TUNNEL_ID=your_cloudflared_tunnel_id
|
||||
CF_DOMAIN=changeme.org
|
||||
CF_ACCOUNT_ID=your_cloudflare_account_id
|
||||
|
||||
# Database Configuration (PostgreSQL for Listmonk)
|
||||
POSTGRES_USER=listmonk
|
||||
@ -279,12 +290,14 @@ N8N_ENCRYPTION_KEY=changeMe
|
||||
GENERIC_TIMEZONE=UTC
|
||||
|
||||
# Nocodb Configuration
|
||||
NOCODB_PORT=${NOCODB_PORT:-8090}
|
||||
NOCODB_JWT_SECRET=changeMe
|
||||
NOCODB_DB_NAME=nocodb
|
||||
NOCODB_DB_USER=noco
|
||||
NOCODB_DB_PASSWORD=changeMe
|
||||
HOMEPAGE_VAR_BASE_URL=https://changeme.org
|
||||
|
||||
# Gitea Database Configuration
|
||||
GITEA_DB_PASSWD=changeMe
|
||||
GITEA_DB_ROOT_PASSWORD=changeMe
|
||||
EOL
|
||||
|
||||
echo "New .env file created with conflict-free port assignments."
|
||||
@ -302,6 +315,8 @@ EOL
|
||||
echo "Homepage: ${HOMEPAGE_PORT:-3010}"
|
||||
echo "Gitea Web: ${GITEA_WEB_PORT:-3030}"
|
||||
echo "Gitea SSH: ${GITEA_SSH_PORT:-2222}"
|
||||
echo "Map: ${MAP_PORT:-3000}"
|
||||
echo "Mini QR: ${MINI_QR_PORT:-8089}"
|
||||
echo "================================"
|
||||
}
|
||||
|
||||
@ -404,42 +419,55 @@ update_main_html() {
|
||||
return 0
|
||||
}
|
||||
|
||||
# Function to get Cloudflare API Token and Zone ID
|
||||
get_cloudflare_credentials() {
|
||||
echo ""
|
||||
echo "To use Cloudflare tunnels, you'll need to configure your credentials."
|
||||
echo ""
|
||||
echo "=== Cloudflare Configuration ==="
|
||||
echo ""
|
||||
echo "You'll need:"
|
||||
echo "1. Your Cloudflare API Token (with Zone.DNS and Account.Cloudflare Tunnel permissions)"
|
||||
echo "2. Your Cloudflare Zone ID (found in the Cloudflare dashboard overview)"
|
||||
echo "3. Your Cloudflare Account ID (found in the Cloudflare dashboard)"
|
||||
echo ""
|
||||
echo "These credentials will be used for:"
|
||||
echo "- Creating and configuring tunnels"
|
||||
echo "- Managing DNS records"
|
||||
echo "- Setting up access policies"
|
||||
echo ""
|
||||
}
|
||||
|
||||
# Function to update the tunnel configuration file with new domain
|
||||
update_tunnel_config() {
|
||||
local new_domain=$1
|
||||
local tunnel_id=${2:-"(insert-tunnel-id)"}
|
||||
local creds_path=${3:-"/path/to/credentials/file"}
|
||||
|
||||
if [ ! -f "$TUNNEL_CONFIG_FILE" ]; then
|
||||
echo "Warning: tunnel-config.yml not found at $TUNNEL_CONFIG_FILE"
|
||||
echo "Creating new tunnel configuration file..."
|
||||
|
||||
# Create the file if it doesn't exist
|
||||
create_tunnel_config "$new_domain" "${CF_TUNNEL_ID:-\${CF_TUNNEL_ID}}"
|
||||
return $?
|
||||
fi
|
||||
# Create directory if it doesn't exist
|
||||
mkdir -p "$TUNNEL_CONFIG_DIR"
|
||||
|
||||
echo "Updating tunnel configuration with new domain..."
|
||||
|
||||
# Create a backup of the tunnel-config.yml file
|
||||
local timestamp=$(date +"%Y%m%d_%H%M%S")
|
||||
local backup_file="${TUNNEL_CONFIG_FILE}.backup_${timestamp}"
|
||||
cp "$TUNNEL_CONFIG_FILE" "$backup_file"
|
||||
echo "Created backup of tunnel-config.yml at $backup_file"
|
||||
|
||||
# Since the current file has all entries as cmlite.org pointing to port 3010,
|
||||
# we need to recreate it with the proper configuration
|
||||
echo "Regenerating tunnel configuration with correct service mappings..."
|
||||
# Create a backup if file exists
|
||||
if [ -f "$TUNNEL_CONFIG_FILE" ]; then
|
||||
local timestamp=$(date +"%Y%m%d_%H%M%S")
|
||||
local backup_file="${TUNNEL_CONFIG_FILE}.backup_${timestamp}"
|
||||
cp "$TUNNEL_CONFIG_FILE" "$backup_file"
|
||||
echo "Created backup of tunnel-config.yml at $backup_file"
|
||||
fi
|
||||
|
||||
# Load current environment variables to get port numbers
|
||||
load_env_vars
|
||||
|
||||
# Recreate the tunnel configuration with proper mappings
|
||||
# Create/update the tunnel configuration
|
||||
cat > "$TUNNEL_CONFIG_FILE" << EOL
|
||||
# filepath: /home/bunker-admin/changemaker.lite/configs/cloudflare/tunnel-config.yml
|
||||
# Cloudflare Tunnel Configuration
|
||||
# Auto-generated by Changemaker Configuration Wizard
|
||||
|
||||
tunnel: ${CF_TUNNEL_ID:-\${CF_TUNNEL_ID}} # e.g. 1234567890abcdef
|
||||
credentials-file: /home/coder/.cloudflared/${CF_TUNNEL_ID:-\${CF_TUNNEL_ID}}.json # e.g. /home/coder/.cloudflared/[insert tunnel number].json
|
||||
tunnel: $tunnel_id # e.g. 1234567890abcdef
|
||||
credentials-file: $creds_path # e.g. /home/bunker-admin/.cloudflared/[insert tunnel number].json
|
||||
ingress:
|
||||
|
||||
- hostname: homepage.$new_domain
|
||||
@ -449,13 +477,13 @@ ingress:
|
||||
service: http://localhost:${CODE_SERVER_PORT:-8888}
|
||||
|
||||
- hostname: listmonk.$new_domain
|
||||
service: http://localhost:${LISTMONK_PORT:-9000}
|
||||
service: http://localhost:${LISTMONK_PORT:-9001}
|
||||
|
||||
- hostname: docs.$new_domain
|
||||
service: http://localhost:${MKDOCS_PORT:-4000}
|
||||
|
||||
- hostname: $new_domain
|
||||
service: http://localhost:${MKDOCS_SITE_SERVER_PORT:-4001}
|
||||
service: http://localhost:${MKDOCS_SITE_SERVER_PORT:-4002}
|
||||
|
||||
- hostname: n8n.$new_domain
|
||||
service: http://localhost:${N8N_PORT:-5678}
|
||||
@ -466,64 +494,20 @@ ingress:
|
||||
- hostname: git.$new_domain
|
||||
service: http://localhost:${GITEA_WEB_PORT:-3030}
|
||||
|
||||
- hostname: map.$new_domain
|
||||
service: http://localhost:${MAP_PORT:-3000}
|
||||
|
||||
- hostname: qr.$new_domain
|
||||
service: http://localhost:${MINI_QR_PORT:-8089}
|
||||
|
||||
# Catch-all rule (required)
|
||||
- service: http_status:404
|
||||
EOL
|
||||
|
||||
echo "✅ Regenerated tunnel configuration with correct service mappings for domain: $new_domain"
|
||||
echo "✅ Updated tunnel configuration for domain: $new_domain"
|
||||
return 0
|
||||
}
|
||||
|
||||
# Function to get Cloudflare API Token and Zone ID
|
||||
get_cloudflare_credentials() {
|
||||
echo ""
|
||||
echo "To use the DNS setup script, you'll need Cloudflare credentials."
|
||||
echo "You can find these values in your Cloudflare dashboard:"
|
||||
echo " - API Token: https://dash.cloudflare.com/profile/api-tokens"
|
||||
echo " (Create a token with Zone:DNS:Edit and Access:Apps:Edit permissions)"
|
||||
echo " - Zone ID: On your domain's overview page"
|
||||
echo ""
|
||||
}
|
||||
|
||||
# Function to show tunnel setup instructions
|
||||
show_tunnel_instructions() {
|
||||
local domain=$1
|
||||
|
||||
echo ""
|
||||
echo "=== Cloudflare Tunnel Setup Instructions ==="
|
||||
echo ""
|
||||
echo "To complete the tunnel setup:"
|
||||
echo ""
|
||||
echo "1. Install cloudflared on your server:"
|
||||
echo " https://developers.cloudflare.com/cloudflare-one/connections/connect-apps/install-and-setup/installation"
|
||||
echo ""
|
||||
echo "2. Create a tunnel using the Cloudflare dashboard or run:"
|
||||
echo " cloudflared tunnel create changemaker-tunnel"
|
||||
echo ""
|
||||
echo "3. Copy the credentials file to the correct location:"
|
||||
echo " mkdir -p /home/coder/.cloudflared"
|
||||
echo " cp ~/.cloudflared/[TUNNEL-ID].json /home/coder/.cloudflared/"
|
||||
echo ""
|
||||
echo "4. Update your .env with the correct CF_TUNNEL_ID if not already done"
|
||||
echo ""
|
||||
echo "5. Start the tunnel with your configuration file:"
|
||||
echo " cloudflared tunnel --config $TUNNEL_CONFIG_FILE run"
|
||||
echo ""
|
||||
echo "6. After verifying it works, you can create a systemd service for automatic startup:"
|
||||
echo " sudo cloudflared service install"
|
||||
echo ""
|
||||
echo "7. Your services will be available at the following URLs:"
|
||||
echo " - Documentation: https://$domain"
|
||||
echo " - Homepage: https://homepage.$domain"
|
||||
echo " - Code Server: https://code.$domain"
|
||||
echo " - Listmonk: https://listmonk.$domain"
|
||||
echo " - N8N: https://n8n.$domain"
|
||||
echo " - NocoDB: https://db.$domain"
|
||||
echo " - MkDocs Dev: https://docs.$domain"
|
||||
echo " - Gitea: https://git.$domain"
|
||||
echo ""
|
||||
}
|
||||
|
||||
# Function to load environment variables from .env file
|
||||
load_env_vars() {
|
||||
if [ -f "$ENV_FILE" ]; then
|
||||
@ -536,6 +520,50 @@ load_env_vars() {
|
||||
fi
|
||||
}
|
||||
|
||||
# Function to update the map's .env file with domain settings
|
||||
update_map_env() {
|
||||
local new_domain=$1
|
||||
|
||||
if [ ! -f "$MAP_ENV_FILE" ]; then
|
||||
echo "Warning: Map .env file not found at $MAP_ENV_FILE"
|
||||
return 1
|
||||
fi
|
||||
|
||||
echo "Updating map .env file with new domain settings..."
|
||||
|
||||
# Create a backup of the map's .env file
|
||||
local timestamp=$(date +"%Y%m%d_%H%M%S")
|
||||
local backup_file="${MAP_ENV_FILE}.backup_${timestamp}"
|
||||
cp "$MAP_ENV_FILE" "$backup_file"
|
||||
echo "Created backup of map .env at $backup_file"
|
||||
|
||||
# Update COOKIE_DOMAIN
|
||||
if grep -q "^COOKIE_DOMAIN=" "$MAP_ENV_FILE"; then
|
||||
sed -i "s|^COOKIE_DOMAIN=.*|COOKIE_DOMAIN=.$new_domain|" "$MAP_ENV_FILE"
|
||||
else
|
||||
echo "COOKIE_DOMAIN=.$new_domain" >> "$MAP_ENV_FILE"
|
||||
fi
|
||||
|
||||
# Update ALLOWED_ORIGINS
|
||||
local allowed_origins="https://map.$new_domain,http://localhost:3000"
|
||||
if grep -q "^ALLOWED_ORIGINS=" "$MAP_ENV_FILE"; then
|
||||
sed -i "s|^ALLOWED_ORIGINS=.*|ALLOWED_ORIGINS=$allowed_origins|" "$MAP_ENV_FILE"
|
||||
else
|
||||
echo "ALLOWED_ORIGINS=$allowed_origins" >> "$MAP_ENV_FILE"
|
||||
fi
|
||||
|
||||
# Also update the NOCODB URLs if they contain domain references
|
||||
sed -i "s|example\.org|$new_domain|g" "$MAP_ENV_FILE"
|
||||
sed -i "s|changeme\.org|$new_domain|g" "$MAP_ENV_FILE"
|
||||
sed -i "s|albertademocracytaskforce\.org|$new_domain|g" "$MAP_ENV_FILE"
|
||||
|
||||
echo "✅ Updated map .env file with:"
|
||||
echo " - COOKIE_DOMAIN=.$new_domain"
|
||||
echo " - ALLOWED_ORIGINS=$allowed_origins"
|
||||
echo " - Updated all NocoDB URLs to use $new_domain"
|
||||
return 0
|
||||
}
|
||||
|
||||
# Initialize a new .env file if it doesn't exist
|
||||
if [ ! -f "$ENV_FILE" ]; then
|
||||
echo "No .env file found. Creating a new one from scratch."
|
||||
@ -579,8 +607,16 @@ update_env_var "CF_DOMAIN" "$domain_name"
|
||||
update_env_var "GITEA_DOMAIN" "git.$domain_name"
|
||||
update_env_var "GITEA_ROOT_URL" "https://git.$domain_name"
|
||||
|
||||
# Update cookie and CORS settings
|
||||
update_env_var "COOKIE_DOMAIN" ".$domain_name"
|
||||
update_env_var "ALLOWED_ORIGINS" "https://map.$domain_name,http://localhost:3000"
|
||||
|
||||
echo "Domain settings updated successfully!"
|
||||
|
||||
# Update the map's .env file
|
||||
echo -e "\nUpdating map configuration..."
|
||||
update_map_env "$domain_name"
|
||||
|
||||
# Cloudflare Configuration
|
||||
echo -e "\n---- Cloudflare Configuration ----"
|
||||
get_cloudflare_credentials
|
||||
@ -588,35 +624,43 @@ get_cloudflare_credentials
|
||||
read -p "Do you want to configure Cloudflare settings now? [Y/n]: " configure_cf
|
||||
|
||||
if [[ ! "$configure_cf" =~ ^[Nn]$ ]]; then
|
||||
# Get Cloudflare API Token
|
||||
# Get Cloudflare API token
|
||||
read -p "Enter your Cloudflare API Token: " cf_api_token
|
||||
while [ -z "$cf_api_token" ] || [ "$cf_api_token" == "your_cloudflare_api_token" ]; do
|
||||
echo "API Token is required. Please enter a valid token."
|
||||
read -p "Enter your Cloudflare API Token: " cf_api_token
|
||||
done
|
||||
if [ -z "$cf_api_token" ] || [ "$cf_api_token" = "your_cloudflare_api_token" ]; then
|
||||
echo "Warning: API token is required for Cloudflare integration"
|
||||
cf_api_token="your_cloudflare_api_token"
|
||||
fi
|
||||
update_env_var "CF_API_TOKEN" "$cf_api_token"
|
||||
|
||||
# Get Cloudflare Zone ID
|
||||
read -p "Enter your Cloudflare Zone ID: " cf_zone_id
|
||||
while [ -z "$cf_zone_id" ] || [ "$cf_zone_id" == "your_cloudflare_zone_id" ]; do
|
||||
echo "Zone ID is required. Please enter a valid Zone ID."
|
||||
read -p "Enter your Cloudflare Zone ID: " cf_zone_id
|
||||
done
|
||||
|
||||
# Optional: Get Account ID now
|
||||
read -p "Enter your Cloudflare Account ID (optional, can be added later): " cf_account_id
|
||||
|
||||
# Update .env file with Cloudflare credentials
|
||||
update_env_var "CF_API_TOKEN" "$cf_api_token"
|
||||
update_env_var "CF_ZONE_ID" "$cf_zone_id"
|
||||
update_env_var "CF_DOMAIN" "$domain_name"
|
||||
|
||||
if [ ! -z "$cf_account_id" ]; then
|
||||
update_env_var "CF_ACCOUNT_ID" "$cf_account_id"
|
||||
if [ -z "$cf_zone_id" ] || [ "$cf_zone_id" = "your_cloudflare_zone_id" ]; then
|
||||
echo "Warning: Zone ID is required for DNS configuration"
|
||||
cf_zone_id="your_cloudflare_zone_id"
|
||||
fi
|
||||
update_env_var "CF_ZONE_ID" "$cf_zone_id"
|
||||
|
||||
echo "Cloudflare credentials saved successfully!"
|
||||
# Get Cloudflare Account ID
|
||||
read -p "Enter your Cloudflare Account ID: " cf_account_id
|
||||
if [ -z "$cf_account_id" ] || [ "$cf_account_id" = "your_cloudflare_account_id" ]; then
|
||||
echo "Warning: Account ID is required for tunnel operations"
|
||||
cf_account_id="your_cloudflare_account_id"
|
||||
fi
|
||||
update_env_var "CF_ACCOUNT_ID" "$cf_account_id"
|
||||
|
||||
# Note: CF_TUNNEL_ID will be set by start-production.sh when the tunnel is created
|
||||
update_env_var "CF_TUNNEL_ID" "will_be_set_by_start_production"
|
||||
|
||||
echo ""
|
||||
echo "Cloudflare configuration saved to .env file."
|
||||
echo ""
|
||||
echo "To complete the setup and deploy your services:"
|
||||
echo "1. Start your services with: docker compose up -d"
|
||||
echo "2. Run ./start-production.sh to configure the Cloudflare tunnel"
|
||||
echo ""
|
||||
else
|
||||
echo "Skipping Cloudflare configuration. You can configure it later by editing the .env file."
|
||||
echo "Skipping Cloudflare configuration."
|
||||
echo "You'll need to configure Cloudflare settings manually before running start-production.sh."
|
||||
fi
|
||||
|
||||
# Update the site_url in mkdocs.yml
|
||||
@ -631,10 +675,6 @@ update_services_yaml "$domain_name"
|
||||
echo -e "\nUpdating login URL in main.html..."
|
||||
update_main_html "$domain_name"
|
||||
|
||||
# Update the tunnel configuration file
|
||||
echo -e "\nUpdating tunnel configuration..."
|
||||
update_tunnel_config "$domain_name"
|
||||
|
||||
# Listmonk Admin Credentials configuration
|
||||
echo -e "\n---- Listmonk Admin Credentials ----"
|
||||
read -p "Enter Listmonk admin email/username [default: admin@example.com]: " listmonk_user
|
||||
@ -692,7 +732,7 @@ update_env_var "NOCODB_JWT_SECRET" "$nocodb_jwt_secret"
|
||||
nocodb_db_password=$(generate_password 20)
|
||||
update_env_var "NOCODB_DB_PASSWORD" "$nocodb_db_password"
|
||||
|
||||
# Generate and update Gitea passwords
|
||||
# Generate and update Gitea passwords (these should already exist in the file)
|
||||
gitea_db_password=$(generate_password 20)
|
||||
update_env_var "GITEA_DB_PASSWD" "$gitea_db_password"
|
||||
|
||||
@ -704,14 +744,16 @@ echo "Secure passwords generated and updated."
|
||||
echo -e "\n✅ Configuration completed successfully!"
|
||||
echo "Your .env file has been configured with:"
|
||||
echo "- Domain: $domain_name"
|
||||
echo "- Cookie Domain: .$domain_name"
|
||||
echo "- Allowed Origins: https://map.$domain_name,http://localhost:3000"
|
||||
echo "- Map .env updated with domain settings"
|
||||
echo "- Listmonk Admin: $listmonk_user"
|
||||
echo "- N8N Admin Email: $n8n_email"
|
||||
echo "- Secure random passwords for database, encryption, and NocoDB"
|
||||
if [[ ! "$configure_cf" =~ ^[Nn]$ ]]; then
|
||||
echo "- Cloudflare credentials for DNS management"
|
||||
fi
|
||||
echo "- Tunnel configuration updated at: $TUNNEL_CONFIG_FILE"
|
||||
echo -e "\nYour .env file is located at: $ENV_FILE"
|
||||
echo "A backup of your original .env file was created before modifications."
|
||||
|
||||
echo ""
|
||||
echo "======================================"
|
||||
echo "Next Steps:"
|
||||
@ -728,6 +770,8 @@ echo " - Documentation: http://localhost:${MKDOCS_PORT:-4000}"
|
||||
echo " - n8n: http://localhost:${N8N_PORT:-5678}"
|
||||
echo " - NocoDB: http://localhost:${NOCODB_PORT:-8090}"
|
||||
echo " - Gitea: http://localhost:${GITEA_WEB_PORT:-3030}"
|
||||
echo " - Map: http://localhost:${MAP_PORT:-3000}"
|
||||
echo " - Mini QR: http://localhost:${MINI_QR_PORT:-8089}"
|
||||
echo ""
|
||||
echo "3. When ready for production:"
|
||||
echo " ./start-production.sh"
|
||||
|
||||
@ -0,0 +1 @@
|
||||
{"AccountTag":"a421828402ca13fbcaad955f285f16f6","TunnelSecret":"949mtkdN202INtEohadCgnEe7QXykBL26dq2uQMt+HQ=","TunnelID":"843f83a4-247a-4c29-8a7e-cde50e2f4222","Endpoint":""}
|
||||
@ -1,34 +1,27 @@
|
||||
# filepath: /home/bunker-admin/changemaker.lite/configs/cloudflare/tunnel-config.yml
|
||||
# Cloudflare Tunnel Configuration
|
||||
# Auto-generated by Changemaker Configuration Wizard
|
||||
# Cloudflare Tunnel Configuration for cmlite.org
|
||||
# Generated by Changemaker.lite start-production.sh on Sun 29 Jun 2025 09:10:15 PM MDT
|
||||
|
||||
tunnel: your_cloudflared_tunnel_id} # e.g. 1234567890abcdef
|
||||
credentials-file: /home/coder/.cloudflared/your_cloudflared_tunnel_id}.json # e.g. /home/coder/.cloudflared/[insert tunnel number].json
|
||||
tunnel: 843f83a4-247a-4c29-8a7e-cde50e2f4222
|
||||
credentials-file: /mnt/storagessd1tb/changemaker.lite.dev/changemaker.lite/configs/cloudflare/843f83a4-247a-4c29-8a7e-cde50e2f4222.json
|
||||
ingress:
|
||||
|
||||
- hostname: homepage.cmlite.org
|
||||
service: http://localhost:3010
|
||||
|
||||
- hostname: code.cmlite.org
|
||||
service: http://localhost:8888
|
||||
|
||||
- hostname: listmonk.cmlite.org
|
||||
service: http://localhost:9001
|
||||
|
||||
- hostname: docs.cmlite.org
|
||||
service: http://localhost:4000
|
||||
|
||||
- hostname: cmlite.org
|
||||
service: http://localhost:4002
|
||||
|
||||
- hostname: n8n.cmlite.org
|
||||
service: http://localhost:5678
|
||||
|
||||
- hostname: db.cmlite.org
|
||||
service: http://localhost:8090
|
||||
|
||||
- hostname: git.cmlite.org
|
||||
service: http://localhost:3030
|
||||
|
||||
# Catch-all rule (required)
|
||||
- hostname: map.cmlite.org
|
||||
service: http://localhost:3000
|
||||
- hostname: qr.cmlite.org
|
||||
service: http://localhost:8089
|
||||
- service: http_status:404
|
||||
|
||||
@ -1,34 +0,0 @@
|
||||
# filepath: /home/bunker-admin/changemaker.lite/configs/cloudflare/tunnel-config.yml
|
||||
# Cloudflare Tunnel Configuration
|
||||
# Auto-generated by Changemaker Configuration Wizard
|
||||
|
||||
tunnel: ${CF_TUNNEL_ID} # e.g. 1234567890abcdef
|
||||
credentials-file: /home/coder/.cloudflared/${CF_TUNNEL_ID}.json # e.g. /home/coder/.cloudflared/[insert tunnel number].json
|
||||
ingress:
|
||||
|
||||
- hostname: homepage.test.com
|
||||
service: http://localhost:3010
|
||||
|
||||
- hostname: code.test.com
|
||||
service: http://localhost:8888
|
||||
|
||||
- hostname: listmonk.test.com
|
||||
service: http://localhost:9001
|
||||
|
||||
- hostname: docs.test.com
|
||||
service: http://localhost:4000
|
||||
|
||||
- hostname: test.com
|
||||
service: http://localhost:4002
|
||||
|
||||
- hostname: n8n.test.com
|
||||
service: http://localhost:5678
|
||||
|
||||
- hostname: db.test.com
|
||||
service: http://localhost:8090
|
||||
|
||||
- hostname: git.test.com
|
||||
service: http://localhost:3030
|
||||
|
||||
# Catch-all rule (required)
|
||||
- service: http_status:404
|
||||
@ -1,34 +0,0 @@
|
||||
# filepath: /home/bunker-admin/changemaker.lite/configs/cloudflare/tunnel-config.yml
|
||||
# Cloudflare Tunnel Configuration
|
||||
# Auto-generated by Changemaker Configuration Wizard
|
||||
|
||||
tunnel: ${CF_TUNNEL_ID} # e.g. 1234567890abcdef
|
||||
credentials-file: /home/coder/.cloudflared/${CF_TUNNEL_ID}.json # e.g. /home/coder/.cloudflared/[insert tunnel number].json
|
||||
ingress:
|
||||
|
||||
- hostname: cmlite.org
|
||||
service: http://localhost:3010
|
||||
|
||||
- hostname: cmlite.org
|
||||
service: http://localhost:3010
|
||||
|
||||
- hostname: cmlite.org
|
||||
service: http://localhost:3010
|
||||
|
||||
- hostname: cmlite.org
|
||||
service: http://localhost:3010
|
||||
|
||||
- hostname: cmlite.org
|
||||
service: http://localhost:3010
|
||||
|
||||
- hostname: cmlite.org
|
||||
service: http://localhost:3010
|
||||
|
||||
- hostname: cmlite.org
|
||||
service: http://localhost:3010
|
||||
|
||||
- hostname: cmlite.org
|
||||
service: http://localhost:3010
|
||||
|
||||
# Catch-all rule (required)
|
||||
- service: http_status:404
|
||||
@ -190,3 +190,514 @@
|
||||
[2025-05-28T14:56:56.936Z] error: <dockerStatsService> Error: connect EACCES /var/run/docker.sock
|
||||
at PipeConnectWrap.afterConnect [as oncomplete] (node:net:1636:16)
|
||||
at PipeConnectWrap.callbackTrampoline (node:internal/async_hooks:130:17)
|
||||
[2025-06-30T03:14:15.516Z] error: undefined
|
||||
[2025-06-30T03:14:15.521Z] error: TypeError: Invalid URL
|
||||
at new URL (node:internal/url:818:25)
|
||||
at d (/app/.next/server/pages/api/releases.js:1:5196)
|
||||
at h (/app/.next/server/pages/api/services/proxy.js:45:33437)
|
||||
at async X (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/compiled/next-server/pages-api.runtime.prod.js:20:18441)
|
||||
at async z.render (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/compiled/next-server/pages-api.runtime.prod.js:20:19237)
|
||||
at async NextNodeServer.runApi (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/next-server.js:671:9)
|
||||
at async NextNodeServer.handleCatchallRenderRequest (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/next-server.js:302:37)
|
||||
at async NextNodeServer.handleRequestImpl (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/base-server.js:899:17)
|
||||
at async invokeRender (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/lib/router-server.js:237:21)
|
||||
at async handleRequest (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/lib/router-server.js:428:24)
|
||||
[2025-06-30T03:14:21.458Z] error: undefined
|
||||
[2025-06-30T03:14:21.460Z] error: TypeError: Invalid URL
|
||||
at new URL (node:internal/url:818:25)
|
||||
at d (/app/.next/server/pages/api/releases.js:1:5196)
|
||||
at h (/app/.next/server/pages/api/services/proxy.js:45:33437)
|
||||
at async X (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/compiled/next-server/pages-api.runtime.prod.js:20:18441)
|
||||
at async z.render (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/compiled/next-server/pages-api.runtime.prod.js:20:19237)
|
||||
at async NextNodeServer.runApi (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/next-server.js:671:9)
|
||||
at async NextNodeServer.handleCatchallRenderRequest (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/next-server.js:302:37)
|
||||
at async NextNodeServer.handleRequestImpl (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/base-server.js:899:17)
|
||||
at async invokeRender (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/lib/router-server.js:237:21)
|
||||
at async handleRequest (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/lib/router-server.js:428:24)
|
||||
[2025-06-30T03:14:26.553Z] error: undefined
|
||||
[2025-06-30T03:14:26.554Z] error: TypeError: Invalid URL
|
||||
at new URL (node:internal/url:818:25)
|
||||
at d (/app/.next/server/pages/api/releases.js:1:5196)
|
||||
at h (/app/.next/server/pages/api/services/proxy.js:45:33437)
|
||||
at async X (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/compiled/next-server/pages-api.runtime.prod.js:20:18441)
|
||||
at async z.render (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/compiled/next-server/pages-api.runtime.prod.js:20:19237)
|
||||
at async NextNodeServer.runApi (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/next-server.js:671:9)
|
||||
at async NextNodeServer.handleCatchallRenderRequest (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/next-server.js:302:37)
|
||||
at async NextNodeServer.handleRequestImpl (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/base-server.js:899:17)
|
||||
at async invokeRender (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/lib/router-server.js:237:21)
|
||||
at async handleRequest (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/lib/router-server.js:428:24)
|
||||
[2025-06-30T03:14:41.640Z] error: undefined
|
||||
[2025-06-30T03:14:41.641Z] error: TypeError: Invalid URL
|
||||
at new URL (node:internal/url:818:25)
|
||||
at d (/app/.next/server/pages/api/releases.js:1:5196)
|
||||
at h (/app/.next/server/pages/api/services/proxy.js:45:33437)
|
||||
at async X (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/compiled/next-server/pages-api.runtime.prod.js:20:18441)
|
||||
at async z.render (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/compiled/next-server/pages-api.runtime.prod.js:20:19237)
|
||||
at async NextNodeServer.runApi (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/next-server.js:671:9)
|
||||
at async NextNodeServer.handleCatchallRenderRequest (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/next-server.js:302:37)
|
||||
at async NextNodeServer.handleRequestImpl (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/base-server.js:899:17)
|
||||
at async invokeRender (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/lib/router-server.js:237:21)
|
||||
at async handleRequest (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/lib/router-server.js:428:24)
|
||||
[2025-06-30T03:15:25.889Z] error: undefined
|
||||
[2025-06-30T03:15:25.891Z] error: TypeError: Invalid URL
|
||||
at new URL (node:internal/url:818:25)
|
||||
at d (/app/.next/server/pages/api/releases.js:1:5196)
|
||||
at h (/app/.next/server/pages/api/services/proxy.js:45:33437)
|
||||
at async X (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/compiled/next-server/pages-api.runtime.prod.js:20:18441)
|
||||
at async z.render (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/compiled/next-server/pages-api.runtime.prod.js:20:19237)
|
||||
at async NextNodeServer.runApi (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/next-server.js:671:9)
|
||||
at async NextNodeServer.handleCatchallRenderRequest (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/next-server.js:302:37)
|
||||
at async NextNodeServer.handleRequestImpl (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/base-server.js:899:17)
|
||||
at async invokeRender (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/lib/router-server.js:237:21)
|
||||
at async handleRequest (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/lib/router-server.js:428:24)
|
||||
[2025-06-30T03:15:31.720Z] error: undefined
|
||||
[2025-06-30T03:15:31.721Z] error: TypeError: Invalid URL
|
||||
at new URL (node:internal/url:818:25)
|
||||
at d (/app/.next/server/pages/api/releases.js:1:5196)
|
||||
at h (/app/.next/server/pages/api/services/proxy.js:45:33437)
|
||||
at async X (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/compiled/next-server/pages-api.runtime.prod.js:20:18441)
|
||||
at async z.render (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/compiled/next-server/pages-api.runtime.prod.js:20:19237)
|
||||
at async NextNodeServer.runApi (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/next-server.js:671:9)
|
||||
at async NextNodeServer.handleCatchallRenderRequest (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/next-server.js:302:37)
|
||||
at async NextNodeServer.handleRequestImpl (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/base-server.js:899:17)
|
||||
at async invokeRender (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/lib/router-server.js:237:21)
|
||||
at async handleRequest (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/lib/router-server.js:428:24)
|
||||
[2025-06-30T03:15:35.980Z] error: undefined
|
||||
[2025-06-30T03:15:35.981Z] error: TypeError: Invalid URL
|
||||
at new URL (node:internal/url:818:25)
|
||||
at d (/app/.next/server/pages/api/releases.js:1:5196)
|
||||
at h (/app/.next/server/pages/api/services/proxy.js:45:33437)
|
||||
at async X (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/compiled/next-server/pages-api.runtime.prod.js:20:18441)
|
||||
at async z.render (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/compiled/next-server/pages-api.runtime.prod.js:20:19237)
|
||||
at async NextNodeServer.runApi (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/next-server.js:671:9)
|
||||
at async NextNodeServer.handleCatchallRenderRequest (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/next-server.js:302:37)
|
||||
at async NextNodeServer.handleRequestImpl (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/base-server.js:899:17)
|
||||
at async invokeRender (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/lib/router-server.js:237:21)
|
||||
at async handleRequest (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/lib/router-server.js:428:24)
|
||||
[2025-06-30T03:16:01.061Z] error: undefined
|
||||
[2025-06-30T03:16:01.062Z] error: TypeError: Invalid URL
|
||||
at new URL (node:internal/url:818:25)
|
||||
at d (/app/.next/server/pages/api/releases.js:1:5196)
|
||||
at h (/app/.next/server/pages/api/services/proxy.js:45:33437)
|
||||
at async X (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/compiled/next-server/pages-api.runtime.prod.js:20:18441)
|
||||
at async z.render (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/compiled/next-server/pages-api.runtime.prod.js:20:19237)
|
||||
at async NextNodeServer.runApi (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/next-server.js:671:9)
|
||||
at async NextNodeServer.handleCatchallRenderRequest (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/next-server.js:302:37)
|
||||
at async NextNodeServer.handleRequestImpl (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/base-server.js:899:17)
|
||||
at async invokeRender (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/lib/router-server.js:237:21)
|
||||
at async handleRequest (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/lib/router-server.js:428:24)
|
||||
[2025-06-30T03:16:11.809Z] error: undefined
|
||||
[2025-06-30T03:16:11.810Z] error: TypeError: Invalid URL
|
||||
at new URL (node:internal/url:818:25)
|
||||
at d (/app/.next/server/pages/api/releases.js:1:5196)
|
||||
at h (/app/.next/server/pages/api/services/proxy.js:45:33437)
|
||||
at async X (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/compiled/next-server/pages-api.runtime.prod.js:20:18441)
|
||||
at async z.render (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/compiled/next-server/pages-api.runtime.prod.js:20:19237)
|
||||
at async NextNodeServer.runApi (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/next-server.js:671:9)
|
||||
at async NextNodeServer.handleCatchallRenderRequest (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/next-server.js:302:37)
|
||||
at async NextNodeServer.handleRequestImpl (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/base-server.js:899:17)
|
||||
at async invokeRender (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/lib/router-server.js:237:21)
|
||||
at async handleRequest (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/lib/router-server.js:428:24)
|
||||
[2025-06-30T03:16:26.149Z] error: undefined
|
||||
[2025-06-30T03:16:26.150Z] error: TypeError: Invalid URL
|
||||
at new URL (node:internal/url:818:25)
|
||||
at d (/app/.next/server/pages/api/releases.js:1:5196)
|
||||
at h (/app/.next/server/pages/api/services/proxy.js:45:33437)
|
||||
at async X (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/compiled/next-server/pages-api.runtime.prod.js:20:18441)
|
||||
at async z.render (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/compiled/next-server/pages-api.runtime.prod.js:20:19237)
|
||||
at async NextNodeServer.runApi (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/next-server.js:671:9)
|
||||
at async NextNodeServer.handleCatchallRenderRequest (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/next-server.js:302:37)
|
||||
at async NextNodeServer.handleRequestImpl (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/base-server.js:899:17)
|
||||
at async invokeRender (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/lib/router-server.js:237:21)
|
||||
at async handleRequest (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/lib/router-server.js:428:24)
|
||||
[2025-06-30T03:17:07.675Z] error: Failed to load services.yaml, please check for errors
|
||||
[2025-06-30T03:17:07.675Z] error: YAMLException: bad indentation of a sequence entry (15:5)
|
||||
|
||||
12 | container: code-server-change ...
|
||||
13 | server: my-docker
|
||||
14 | showStats: false
|
||||
15 | - Listmonk:
|
||||
----------^
|
||||
16 | href: "http://localhost:9000"
|
||||
17 | # href: "https://cmlite.org ...
|
||||
[2025-06-30T03:17:07.755Z] error: Failed to load services.yaml, please check for errors
|
||||
[2025-06-30T03:17:07.757Z] error: <servicesProxy> YAMLException: bad indentation of a sequence entry (15:5)
|
||||
|
||||
12 | container: code-server-change ...
|
||||
13 | server: my-docker
|
||||
14 | showStats: false
|
||||
15 | - Listmonk:
|
||||
----------^
|
||||
16 | href: "http://localhost:9000"
|
||||
17 | # href: "https://cmlite.org ...
|
||||
at generateError (file:///app/node_modules/.pnpm/js-yaml@4.1.0/node_modules/js-yaml/dist/js-yaml.mjs:1273:10)
|
||||
at throwError (file:///app/node_modules/.pnpm/js-yaml@4.1.0/node_modules/js-yaml/dist/js-yaml.mjs:1277:9)
|
||||
at readBlockSequence (file:///app/node_modules/.pnpm/js-yaml@4.1.0/node_modules/js-yaml/dist/js-yaml.mjs:2105:7)
|
||||
at composeNode (file:///app/node_modules/.pnpm/js-yaml@4.1.0/node_modules/js-yaml/dist/js-yaml.mjs:2562:45)
|
||||
at readBlockMapping (file:///app/node_modules/.pnpm/js-yaml@4.1.0/node_modules/js-yaml/dist/js-yaml.mjs:2254:11)
|
||||
at composeNode (file:///app/node_modules/.pnpm/js-yaml@4.1.0/node_modules/js-yaml/dist/js-yaml.mjs:2531:12)
|
||||
at readBlockSequence (file:///app/node_modules/.pnpm/js-yaml@4.1.0/node_modules/js-yaml/dist/js-yaml.mjs:2098:5)
|
||||
at composeNode (file:///app/node_modules/.pnpm/js-yaml@4.1.0/node_modules/js-yaml/dist/js-yaml.mjs:2530:12)
|
||||
at readDocument (file:///app/node_modules/.pnpm/js-yaml@4.1.0/node_modules/js-yaml/dist/js-yaml.mjs:2715:3)
|
||||
at loadDocuments (file:///app/node_modules/.pnpm/js-yaml@4.1.0/node_modules/js-yaml/dist/js-yaml.mjs:2778:5)
|
||||
[2025-06-30T03:17:07.756Z] error: YAMLException: bad indentation of a sequence entry (15:5)
|
||||
|
||||
12 | container: code-server-change ...
|
||||
13 | server: my-docker
|
||||
14 | showStats: false
|
||||
15 | - Listmonk:
|
||||
----------^
|
||||
16 | href: "http://localhost:9000"
|
||||
17 | # href: "https://cmlite.org ...
|
||||
[2025-06-30T03:17:08.098Z] error: <servicesProxy> YAMLException: bad indentation of a sequence entry (15:5)
|
||||
|
||||
12 | container: code-server-change ...
|
||||
13 | server: my-docker
|
||||
14 | showStats: false
|
||||
15 | - Listmonk:
|
||||
----------^
|
||||
16 | href: "http://localhost:9000"
|
||||
17 | # href: "https://cmlite.org ...
|
||||
at generateError (file:///app/node_modules/.pnpm/js-yaml@4.1.0/node_modules/js-yaml/dist/js-yaml.mjs:1273:10)
|
||||
at throwError (file:///app/node_modules/.pnpm/js-yaml@4.1.0/node_modules/js-yaml/dist/js-yaml.mjs:1277:9)
|
||||
at readBlockSequence (file:///app/node_modules/.pnpm/js-yaml@4.1.0/node_modules/js-yaml/dist/js-yaml.mjs:2105:7)
|
||||
at composeNode (file:///app/node_modules/.pnpm/js-yaml@4.1.0/node_modules/js-yaml/dist/js-yaml.mjs:2562:45)
|
||||
at readBlockMapping (file:///app/node_modules/.pnpm/js-yaml@4.1.0/node_modules/js-yaml/dist/js-yaml.mjs:2254:11)
|
||||
at composeNode (file:///app/node_modules/.pnpm/js-yaml@4.1.0/node_modules/js-yaml/dist/js-yaml.mjs:2531:12)
|
||||
at readBlockSequence (file:///app/node_modules/.pnpm/js-yaml@4.1.0/node_modules/js-yaml/dist/js-yaml.mjs:2098:5)
|
||||
at composeNode (file:///app/node_modules/.pnpm/js-yaml@4.1.0/node_modules/js-yaml/dist/js-yaml.mjs:2530:12)
|
||||
at readDocument (file:///app/node_modules/.pnpm/js-yaml@4.1.0/node_modules/js-yaml/dist/js-yaml.mjs:2715:3)
|
||||
at loadDocuments (file:///app/node_modules/.pnpm/js-yaml@4.1.0/node_modules/js-yaml/dist/js-yaml.mjs:2778:5)
|
||||
[2025-06-30T03:17:08.161Z] error: Failed to load services.yaml, please check for errors
|
||||
[2025-06-30T03:17:08.161Z] error: YAMLException: bad indentation of a sequence entry (15:5)
|
||||
|
||||
12 | container: code-server-change ...
|
||||
13 | server: my-docker
|
||||
14 | showStats: false
|
||||
15 | - Listmonk:
|
||||
----------^
|
||||
16 | href: "http://localhost:9000"
|
||||
17 | # href: "https://cmlite.org ...
|
||||
[2025-06-30T03:17:15.271Z] error: Failed to load services.yaml, please check for errors
|
||||
[2025-06-30T03:17:15.271Z] error: YAMLException: bad indentation of a sequence entry (14:5)
|
||||
|
||||
11 | type: docker
|
||||
12 | container: code-server-change ...
|
||||
13 | server: my-docker
|
||||
14 | - Listmonk:
|
||||
----------^
|
||||
15 | href: "http://localhost:9000"
|
||||
16 | # href: "https://cmlite.org ...
|
||||
[2025-06-30T03:17:15.511Z] error: <servicesProxy> YAMLException: bad indentation of a sequence entry (14:5)
|
||||
|
||||
11 | type: docker
|
||||
12 | container: code-server-change ...
|
||||
13 | server: my-docker
|
||||
14 | - Listmonk:
|
||||
----------^
|
||||
15 | href: "http://localhost:9000"
|
||||
16 | # href: "https://cmlite.org ...
|
||||
at generateError (file:///app/node_modules/.pnpm/js-yaml@4.1.0/node_modules/js-yaml/dist/js-yaml.mjs:1273:10)
|
||||
at throwError (file:///app/node_modules/.pnpm/js-yaml@4.1.0/node_modules/js-yaml/dist/js-yaml.mjs:1277:9)
|
||||
at readBlockSequence (file:///app/node_modules/.pnpm/js-yaml@4.1.0/node_modules/js-yaml/dist/js-yaml.mjs:2105:7)
|
||||
at composeNode (file:///app/node_modules/.pnpm/js-yaml@4.1.0/node_modules/js-yaml/dist/js-yaml.mjs:2562:45)
|
||||
at readBlockMapping (file:///app/node_modules/.pnpm/js-yaml@4.1.0/node_modules/js-yaml/dist/js-yaml.mjs:2254:11)
|
||||
at composeNode (file:///app/node_modules/.pnpm/js-yaml@4.1.0/node_modules/js-yaml/dist/js-yaml.mjs:2531:12)
|
||||
at readBlockSequence (file:///app/node_modules/.pnpm/js-yaml@4.1.0/node_modules/js-yaml/dist/js-yaml.mjs:2098:5)
|
||||
at composeNode (file:///app/node_modules/.pnpm/js-yaml@4.1.0/node_modules/js-yaml/dist/js-yaml.mjs:2530:12)
|
||||
at readDocument (file:///app/node_modules/.pnpm/js-yaml@4.1.0/node_modules/js-yaml/dist/js-yaml.mjs:2715:3)
|
||||
at loadDocuments (file:///app/node_modules/.pnpm/js-yaml@4.1.0/node_modules/js-yaml/dist/js-yaml.mjs:2778:5)
|
||||
[2025-06-30T03:17:15.572Z] error: Failed to load services.yaml, please check for errors
|
||||
[2025-06-30T03:17:15.573Z] error: YAMLException: bad indentation of a sequence entry (14:5)
|
||||
|
||||
11 | type: docker
|
||||
12 | container: code-server-change ...
|
||||
13 | server: my-docker
|
||||
14 | - Listmonk:
|
||||
----------^
|
||||
15 | href: "http://localhost:9000"
|
||||
16 | # href: "https://cmlite.org ...
|
||||
[2025-06-30T03:17:45.214Z] error: undefined
|
||||
[2025-06-30T03:17:45.216Z] error: TypeError: Invalid URL
|
||||
at new URL (node:internal/url:818:25)
|
||||
at d (/app/.next/server/pages/api/releases.js:1:5196)
|
||||
at h (/app/.next/server/pages/api/services/proxy.js:45:33437)
|
||||
at async X (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/compiled/next-server/pages-api.runtime.prod.js:20:18441)
|
||||
at async z.render (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/compiled/next-server/pages-api.runtime.prod.js:20:19237)
|
||||
at async NextNodeServer.runApi (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/next-server.js:671:9)
|
||||
at async NextNodeServer.handleCatchallRenderRequest (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/next-server.js:302:37)
|
||||
at async NextNodeServer.handleRequestImpl (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/base-server.js:899:17)
|
||||
at async invokeRender (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/lib/router-server.js:237:21)
|
||||
at async handleRequest (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/lib/router-server.js:428:24)
|
||||
[2025-06-30T03:17:50.333Z] error: undefined
|
||||
[2025-06-30T03:17:50.334Z] error: TypeError: Invalid URL
|
||||
at new URL (node:internal/url:818:25)
|
||||
at d (/app/.next/server/pages/api/releases.js:1:5196)
|
||||
at h (/app/.next/server/pages/api/services/proxy.js:45:33437)
|
||||
at async X (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/compiled/next-server/pages-api.runtime.prod.js:20:18441)
|
||||
at async z.render (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/compiled/next-server/pages-api.runtime.prod.js:20:19237)
|
||||
at async NextNodeServer.runApi (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/next-server.js:671:9)
|
||||
at async NextNodeServer.handleCatchallRenderRequest (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/next-server.js:302:37)
|
||||
at async NextNodeServer.handleRequestImpl (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/base-server.js:899:17)
|
||||
at async invokeRender (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/lib/router-server.js:237:21)
|
||||
at async handleRequest (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/lib/router-server.js:428:24)
|
||||
[2025-06-30T03:17:56.035Z] error: undefined
|
||||
[2025-06-30T03:17:56.036Z] error: TypeError: Invalid URL
|
||||
at new URL (node:internal/url:818:25)
|
||||
at d (/app/.next/server/pages/api/releases.js:1:5196)
|
||||
at h (/app/.next/server/pages/api/services/proxy.js:45:33437)
|
||||
at async X (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/compiled/next-server/pages-api.runtime.prod.js:20:18441)
|
||||
at async z.render (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/compiled/next-server/pages-api.runtime.prod.js:20:19237)
|
||||
at async NextNodeServer.runApi (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/next-server.js:671:9)
|
||||
at async NextNodeServer.handleCatchallRenderRequest (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/next-server.js:302:37)
|
||||
at async NextNodeServer.handleRequestImpl (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/base-server.js:899:17)
|
||||
at async invokeRender (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/lib/router-server.js:237:21)
|
||||
at async handleRequest (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/lib/router-server.js:428:24)
|
||||
[2025-06-30T03:18:01.448Z] error: undefined
|
||||
[2025-06-30T03:18:01.449Z] error: TypeError: Invalid URL
|
||||
at new URL (node:internal/url:818:25)
|
||||
at d (/app/.next/server/pages/api/releases.js:1:5196)
|
||||
at h (/app/.next/server/pages/api/services/proxy.js:45:33437)
|
||||
at async X (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/compiled/next-server/pages-api.runtime.prod.js:20:18441)
|
||||
at async z.render (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/compiled/next-server/pages-api.runtime.prod.js:20:19237)
|
||||
at async NextNodeServer.runApi (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/next-server.js:671:9)
|
||||
at async NextNodeServer.handleCatchallRenderRequest (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/next-server.js:302:37)
|
||||
at async NextNodeServer.handleRequestImpl (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/base-server.js:899:17)
|
||||
at async invokeRender (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/lib/router-server.js:237:21)
|
||||
at async handleRequest (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/lib/router-server.js:428:24)
|
||||
[2025-06-30T03:18:15.473Z] error: undefined
|
||||
[2025-06-30T03:18:15.474Z] error: TypeError: Invalid URL
|
||||
at new URL (node:internal/url:818:25)
|
||||
at d (/app/.next/server/pages/api/releases.js:1:5196)
|
||||
at h (/app/.next/server/pages/api/services/proxy.js:45:33437)
|
||||
at async X (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/compiled/next-server/pages-api.runtime.prod.js:20:18441)
|
||||
at async z.render (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/compiled/next-server/pages-api.runtime.prod.js:20:19237)
|
||||
at async NextNodeServer.runApi (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/next-server.js:671:9)
|
||||
at async NextNodeServer.handleCatchallRenderRequest (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/next-server.js:302:37)
|
||||
at async NextNodeServer.handleRequestImpl (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/base-server.js:899:17)
|
||||
at async invokeRender (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/lib/router-server.js:237:21)
|
||||
at async handleRequest (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/lib/router-server.js:428:24)
|
||||
[2025-06-30T03:18:36.889Z] error: undefined
|
||||
[2025-06-30T03:18:36.890Z] error: TypeError: Invalid URL
|
||||
at new URL (node:internal/url:818:25)
|
||||
at d (/app/.next/server/pages/api/releases.js:1:5196)
|
||||
at h (/app/.next/server/pages/api/services/proxy.js:45:33437)
|
||||
at async X (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/compiled/next-server/pages-api.runtime.prod.js:20:18441)
|
||||
at async z.render (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/compiled/next-server/pages-api.runtime.prod.js:20:19237)
|
||||
at async NextNodeServer.runApi (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/next-server.js:671:9)
|
||||
at async NextNodeServer.handleCatchallRenderRequest (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/next-server.js:302:37)
|
||||
at async NextNodeServer.handleRequestImpl (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/base-server.js:899:17)
|
||||
at async invokeRender (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/lib/router-server.js:237:21)
|
||||
at async handleRequest (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/lib/router-server.js:428:24)
|
||||
[2025-06-30T03:19:00.275Z] error: undefined
|
||||
[2025-06-30T03:19:00.276Z] error: TypeError: Invalid URL
|
||||
at new URL (node:internal/url:818:25)
|
||||
at d (/app/.next/server/pages/api/releases.js:1:5196)
|
||||
at h (/app/.next/server/pages/api/services/proxy.js:45:33437)
|
||||
at async X (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/compiled/next-server/pages-api.runtime.prod.js:20:18441)
|
||||
at async z.render (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/compiled/next-server/pages-api.runtime.prod.js:20:19237)
|
||||
at async NextNodeServer.runApi (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/next-server.js:671:9)
|
||||
at async NextNodeServer.handleCatchallRenderRequest (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/next-server.js:302:37)
|
||||
at async NextNodeServer.handleRequestImpl (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/base-server.js:899:17)
|
||||
at async invokeRender (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/lib/router-server.js:237:21)
|
||||
at async handleRequest (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/lib/router-server.js:428:24)
|
||||
[2025-06-30T03:21:04.087Z] error: <servicesProxy> YAMLException: bad indentation of a mapping entry (10:20)
|
||||
|
||||
7 | # href: "https://cmlite.org" # Uncomment ...
|
||||
8 | description: VS Code in the browser
|
||||
9 | icon: mdi-code-braces
|
||||
10 | container: code-server-changemaker
|
||||
-------------------------^
|
||||
11 | server: my-docker
|
||||
12 | - Listmonk:
|
||||
at generateError (file:///app/node_modules/.pnpm/js-yaml@4.1.0/node_modules/js-yaml/dist/js-yaml.mjs:1273:10)
|
||||
at throwError (file:///app/node_modules/.pnpm/js-yaml@4.1.0/node_modules/js-yaml/dist/js-yaml.mjs:1277:9)
|
||||
at readBlockMapping (file:///app/node_modules/.pnpm/js-yaml@4.1.0/node_modules/js-yaml/dist/js-yaml.mjs:2272:7)
|
||||
at composeNode (file:///app/node_modules/.pnpm/js-yaml@4.1.0/node_modules/js-yaml/dist/js-yaml.mjs:2531:12)
|
||||
at readBlockMapping (file:///app/node_modules/.pnpm/js-yaml@4.1.0/node_modules/js-yaml/dist/js-yaml.mjs:2254:11)
|
||||
at composeNode (file:///app/node_modules/.pnpm/js-yaml@4.1.0/node_modules/js-yaml/dist/js-yaml.mjs:2531:12)
|
||||
at readBlockSequence (file:///app/node_modules/.pnpm/js-yaml@4.1.0/node_modules/js-yaml/dist/js-yaml.mjs:2098:5)
|
||||
at composeNode (file:///app/node_modules/.pnpm/js-yaml@4.1.0/node_modules/js-yaml/dist/js-yaml.mjs:2530:12)
|
||||
at readBlockMapping (file:///app/node_modules/.pnpm/js-yaml@4.1.0/node_modules/js-yaml/dist/js-yaml.mjs:2254:11)
|
||||
at composeNode (file:///app/node_modules/.pnpm/js-yaml@4.1.0/node_modules/js-yaml/dist/js-yaml.mjs:2531:12)
|
||||
[2025-06-30T03:21:04.511Z] error: Failed to load services.yaml, please check for errors
|
||||
[2025-06-30T03:21:04.511Z] error: YAMLException: bad indentation of a mapping entry (10:20)
|
||||
|
||||
7 | # href: "https://cmlite.org" # Uncomment ...
|
||||
8 | description: VS Code in the browser
|
||||
9 | icon: mdi-code-braces
|
||||
10 | container: code-server-changemaker
|
||||
-------------------------^
|
||||
11 | server: my-docker
|
||||
12 | - Listmonk:
|
||||
[2025-06-30T03:21:04.585Z] error: Failed to load services.yaml, please check for errors
|
||||
[2025-06-30T03:21:04.585Z] error: YAMLException: bad indentation of a mapping entry (10:20)
|
||||
|
||||
7 | # href: "https://cmlite.org" # Uncomment ...
|
||||
8 | description: VS Code in the browser
|
||||
9 | icon: mdi-code-braces
|
||||
10 | container: code-server-changemaker
|
||||
-------------------------^
|
||||
11 | server: my-docker
|
||||
12 | - Listmonk:
|
||||
[2025-06-30T03:21:04.867Z] error: <servicesProxy> YAMLException: bad indentation of a mapping entry (10:20)
|
||||
|
||||
7 | # href: "https://cmlite.org" # Uncomment ...
|
||||
8 | description: VS Code in the browser
|
||||
9 | icon: mdi-code-braces
|
||||
10 | container: code-server-changemaker
|
||||
-------------------------^
|
||||
11 | server: my-docker
|
||||
12 | - Listmonk:
|
||||
at generateError (file:///app/node_modules/.pnpm/js-yaml@4.1.0/node_modules/js-yaml/dist/js-yaml.mjs:1273:10)
|
||||
at throwError (file:///app/node_modules/.pnpm/js-yaml@4.1.0/node_modules/js-yaml/dist/js-yaml.mjs:1277:9)
|
||||
at readBlockMapping (file:///app/node_modules/.pnpm/js-yaml@4.1.0/node_modules/js-yaml/dist/js-yaml.mjs:2272:7)
|
||||
at composeNode (file:///app/node_modules/.pnpm/js-yaml@4.1.0/node_modules/js-yaml/dist/js-yaml.mjs:2531:12)
|
||||
at readBlockMapping (file:///app/node_modules/.pnpm/js-yaml@4.1.0/node_modules/js-yaml/dist/js-yaml.mjs:2254:11)
|
||||
at composeNode (file:///app/node_modules/.pnpm/js-yaml@4.1.0/node_modules/js-yaml/dist/js-yaml.mjs:2531:12)
|
||||
at readBlockSequence (file:///app/node_modules/.pnpm/js-yaml@4.1.0/node_modules/js-yaml/dist/js-yaml.mjs:2098:5)
|
||||
at composeNode (file:///app/node_modules/.pnpm/js-yaml@4.1.0/node_modules/js-yaml/dist/js-yaml.mjs:2530:12)
|
||||
at readBlockMapping (file:///app/node_modules/.pnpm/js-yaml@4.1.0/node_modules/js-yaml/dist/js-yaml.mjs:2254:11)
|
||||
at composeNode (file:///app/node_modules/.pnpm/js-yaml@4.1.0/node_modules/js-yaml/dist/js-yaml.mjs:2531:12)
|
||||
[2025-06-30T03:21:04.954Z] error: Failed to load services.yaml, please check for errors
|
||||
[2025-06-30T03:21:04.954Z] error: YAMLException: bad indentation of a mapping entry (10:20)
|
||||
|
||||
7 | # href: "https://cmlite.org" # Uncomment ...
|
||||
8 | description: VS Code in the browser
|
||||
9 | icon: mdi-code-braces
|
||||
10 | container: code-server-changemaker
|
||||
-------------------------^
|
||||
11 | server: my-docker
|
||||
12 | - Listmonk:
|
||||
[2025-06-30T03:21:12.819Z] error: undefined
|
||||
[2025-06-30T03:21:12.820Z] error: TypeError: Invalid URL
|
||||
at new URL (node:internal/url:818:25)
|
||||
at d (/app/.next/server/pages/api/releases.js:1:5196)
|
||||
at h (/app/.next/server/pages/api/services/proxy.js:45:33437)
|
||||
at async X (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/compiled/next-server/pages-api.runtime.prod.js:20:18441)
|
||||
at async z.render (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/compiled/next-server/pages-api.runtime.prod.js:20:19237)
|
||||
at async NextNodeServer.runApi (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/next-server.js:671:9)
|
||||
at async NextNodeServer.handleCatchallRenderRequest (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/next-server.js:302:37)
|
||||
at async NextNodeServer.handleRequestImpl (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/base-server.js:899:17)
|
||||
at async invokeRender (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/lib/router-server.js:237:21)
|
||||
at async handleRequest (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/lib/router-server.js:428:24)
|
||||
[2025-06-30T03:21:13.108Z] error: undefined
|
||||
[2025-06-30T03:21:13.110Z] error: TypeError: Invalid URL
|
||||
at new URL (node:internal/url:818:25)
|
||||
at d (/app/.next/server/pages/api/releases.js:1:5196)
|
||||
at h (/app/.next/server/pages/api/services/proxy.js:45:33437)
|
||||
at async X (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/compiled/next-server/pages-api.runtime.prod.js:20:18441)
|
||||
at async z.render (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/compiled/next-server/pages-api.runtime.prod.js:20:19237)
|
||||
at async NextNodeServer.runApi (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/next-server.js:671:9)
|
||||
at async NextNodeServer.handleCatchallRenderRequest (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/next-server.js:302:37)
|
||||
at async NextNodeServer.handleRequestImpl (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/base-server.js:899:17)
|
||||
at async invokeRender (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/lib/router-server.js:237:21)
|
||||
at async handleRequest (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/lib/router-server.js:428:24)
|
||||
[2025-06-30T03:21:18.234Z] error: undefined
|
||||
[2025-06-30T03:21:18.236Z] error: TypeError: Invalid URL
|
||||
at new URL (node:internal/url:818:25)
|
||||
at d (/app/.next/server/pages/api/releases.js:1:5196)
|
||||
at h (/app/.next/server/pages/api/services/proxy.js:45:33437)
|
||||
at async X (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/compiled/next-server/pages-api.runtime.prod.js:20:18441)
|
||||
at async z.render (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/compiled/next-server/pages-api.runtime.prod.js:20:19237)
|
||||
at async NextNodeServer.runApi (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/next-server.js:671:9)
|
||||
at async NextNodeServer.handleCatchallRenderRequest (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/next-server.js:302:37)
|
||||
at async NextNodeServer.handleRequestImpl (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/base-server.js:899:17)
|
||||
at async invokeRender (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/lib/router-server.js:237:21)
|
||||
at async handleRequest (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/lib/router-server.js:428:24)
|
||||
[2025-06-30T03:21:23.680Z] error: undefined
|
||||
[2025-06-30T03:21:23.681Z] error: TypeError: Invalid URL
|
||||
at new URL (node:internal/url:818:25)
|
||||
at d (/app/.next/server/pages/api/releases.js:1:5196)
|
||||
at h (/app/.next/server/pages/api/services/proxy.js:45:33437)
|
||||
at async X (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/compiled/next-server/pages-api.runtime.prod.js:20:18441)
|
||||
at async z.render (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/compiled/next-server/pages-api.runtime.prod.js:20:19237)
|
||||
at async NextNodeServer.runApi (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/next-server.js:671:9)
|
||||
at async NextNodeServer.handleCatchallRenderRequest (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/next-server.js:302:37)
|
||||
at async NextNodeServer.handleRequestImpl (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/base-server.js:899:17)
|
||||
at async invokeRender (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/lib/router-server.js:237:21)
|
||||
at async handleRequest (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/lib/router-server.js:428:24)
|
||||
[2025-06-30T03:21:38.468Z] error: undefined
|
||||
[2025-06-30T03:21:38.469Z] error: TypeError: Invalid URL
|
||||
at new URL (node:internal/url:818:25)
|
||||
at d (/app/.next/server/pages/api/releases.js:1:5196)
|
||||
at h (/app/.next/server/pages/api/services/proxy.js:45:33437)
|
||||
at async X (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/compiled/next-server/pages-api.runtime.prod.js:20:18441)
|
||||
at async z.render (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/compiled/next-server/pages-api.runtime.prod.js:20:19237)
|
||||
at async NextNodeServer.runApi (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/next-server.js:671:9)
|
||||
at async NextNodeServer.handleCatchallRenderRequest (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/next-server.js:302:37)
|
||||
at async NextNodeServer.handleRequestImpl (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/base-server.js:899:17)
|
||||
at async invokeRender (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/lib/router-server.js:237:21)
|
||||
at async handleRequest (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/lib/router-server.js:428:24)
|
||||
[2025-06-30T03:22:04.123Z] error: undefined
|
||||
[2025-06-30T03:22:04.125Z] error: TypeError: Invalid URL
|
||||
at new URL (node:internal/url:818:25)
|
||||
at d (/app/.next/server/pages/api/releases.js:1:5196)
|
||||
at h (/app/.next/server/pages/api/services/proxy.js:45:33437)
|
||||
at async X (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/compiled/next-server/pages-api.runtime.prod.js:20:18441)
|
||||
at async z.render (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/compiled/next-server/pages-api.runtime.prod.js:20:19237)
|
||||
at async NextNodeServer.runApi (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/next-server.js:671:9)
|
||||
at async NextNodeServer.handleCatchallRenderRequest (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/next-server.js:302:37)
|
||||
at async NextNodeServer.handleRequestImpl (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/base-server.js:899:17)
|
||||
at async invokeRender (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/lib/router-server.js:237:21)
|
||||
at async handleRequest (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/lib/router-server.js:428:24)
|
||||
[2025-06-30T03:22:09.222Z] error: undefined
|
||||
[2025-06-30T03:22:09.223Z] error: TypeError: Invalid URL
|
||||
at new URL (node:internal/url:818:25)
|
||||
at d (/app/.next/server/pages/api/releases.js:1:5196)
|
||||
at h (/app/.next/server/pages/api/services/proxy.js:45:33437)
|
||||
at async X (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/compiled/next-server/pages-api.runtime.prod.js:20:18441)
|
||||
at async z.render (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/compiled/next-server/pages-api.runtime.prod.js:20:19237)
|
||||
at async NextNodeServer.runApi (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/next-server.js:671:9)
|
||||
at async NextNodeServer.handleCatchallRenderRequest (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/next-server.js:302:37)
|
||||
at async NextNodeServer.handleRequestImpl (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/base-server.js:899:17)
|
||||
at async invokeRender (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/lib/router-server.js:237:21)
|
||||
at async handleRequest (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/lib/router-server.js:428:24)
|
||||
[2025-06-30T03:22:31.975Z] error: undefined
|
||||
[2025-06-30T03:22:31.976Z] error: TypeError: Invalid URL
|
||||
at new URL (node:internal/url:818:25)
|
||||
at d (/app/.next/server/pages/api/releases.js:1:5196)
|
||||
at h (/app/.next/server/pages/api/services/proxy.js:45:33437)
|
||||
at async X (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/compiled/next-server/pages-api.runtime.prod.js:20:18441)
|
||||
at async z.render (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/compiled/next-server/pages-api.runtime.prod.js:20:19237)
|
||||
at async NextNodeServer.runApi (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/next-server.js:671:9)
|
||||
at async NextNodeServer.handleCatchallRenderRequest (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/next-server.js:302:37)
|
||||
at async NextNodeServer.handleRequestImpl (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/base-server.js:899:17)
|
||||
at async invokeRender (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/lib/router-server.js:237:21)
|
||||
at async handleRequest (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/lib/router-server.js:428:24)
|
||||
[2025-06-30T03:22:34.309Z] error: undefined
|
||||
[2025-06-30T03:22:34.310Z] error: TypeError: Invalid URL
|
||||
at new URL (node:internal/url:818:25)
|
||||
at d (/app/.next/server/pages/api/releases.js:1:5196)
|
||||
at h (/app/.next/server/pages/api/services/proxy.js:45:33437)
|
||||
at async X (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/compiled/next-server/pages-api.runtime.prod.js:20:18441)
|
||||
at async z.render (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/compiled/next-server/pages-api.runtime.prod.js:20:19237)
|
||||
at async NextNodeServer.runApi (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/next-server.js:671:9)
|
||||
at async NextNodeServer.handleCatchallRenderRequest (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/next-server.js:302:37)
|
||||
at async NextNodeServer.handleRequestImpl (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/base-server.js:899:17)
|
||||
at async invokeRender (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/lib/router-server.js:237:21)
|
||||
at async handleRequest (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/lib/router-server.js:428:24)
|
||||
[2025-06-30T03:22:56.905Z] error: undefined
|
||||
[2025-06-30T03:22:56.907Z] error: TypeError: Invalid URL
|
||||
at new URL (node:internal/url:818:25)
|
||||
at d (/app/.next/server/pages/api/releases.js:1:5196)
|
||||
at h (/app/.next/server/pages/api/services/proxy.js:45:33437)
|
||||
at async X (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/compiled/next-server/pages-api.runtime.prod.js:20:18441)
|
||||
at async z.render (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/compiled/next-server/pages-api.runtime.prod.js:20:19237)
|
||||
at async NextNodeServer.runApi (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/next-server.js:671:9)
|
||||
at async NextNodeServer.handleCatchallRenderRequest (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/next-server.js:302:37)
|
||||
at async NextNodeServer.handleRequestImpl (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/base-server.js:899:17)
|
||||
at async invokeRender (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/lib/router-server.js:237:21)
|
||||
at async handleRequest (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/lib/router-server.js:428:24)
|
||||
[2025-06-30T03:23:24.463Z] error: undefined
|
||||
[2025-06-30T03:23:24.464Z] error: TypeError: Invalid URL
|
||||
at new URL (node:internal/url:818:25)
|
||||
at d (/app/.next/server/pages/api/releases.js:1:5196)
|
||||
at h (/app/.next/server/pages/api/services/proxy.js:45:33437)
|
||||
at async X (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/compiled/next-server/pages-api.runtime.prod.js:20:18441)
|
||||
at async z.render (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/compiled/next-server/pages-api.runtime.prod.js:20:19237)
|
||||
at async NextNodeServer.runApi (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/next-server.js:671:9)
|
||||
at async NextNodeServer.handleCatchallRenderRequest (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/next-server.js:302:37)
|
||||
at async NextNodeServer.handleRequestImpl (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/base-server.js:899:17)
|
||||
at async invokeRender (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/lib/router-server.js:237:21)
|
||||
at async handleRequest (/app/node_modules/.pnpm/next@15.3.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/lib/router-server.js:428:24)
|
||||
|
||||
@ -2,86 +2,73 @@
|
||||
# For public access, replace "http://localhost" with your subdomain URLs
|
||||
|
||||
- Essential Tools:
|
||||
|
||||
- Code Server:
|
||||
href: "http://localhost:8888"
|
||||
# href: "https://cmlite.org" # Uncomment for public access
|
||||
description: VS Code in the browser
|
||||
icon: mdi-code-braces
|
||||
widget:
|
||||
type: docker
|
||||
container: code-server-changemaker
|
||||
server: my-docker
|
||||
href: "https://code.cmlite.org"
|
||||
description: VS Code in the browser - Platform Editor
|
||||
container: code-server-changemaker
|
||||
|
||||
- Listmonk:
|
||||
href: "http://localhost:9000"
|
||||
# href: "https://cmlite.org" # Uncomment for public access
|
||||
description: Newsletter & mailing list manager
|
||||
icon: mdi-email-newsletter
|
||||
widget:
|
||||
type: docker
|
||||
container: listmonk_app
|
||||
server: my-docker
|
||||
href: "https://listmonk.cmlite.org"
|
||||
description: Newsletter & mailing list manager
|
||||
container: listmonk_app
|
||||
|
||||
- NocoDB:
|
||||
href: "http://localhost:8090"
|
||||
# href: "https://cmlite.org" # Uncomment for public access
|
||||
description: No-code database platform
|
||||
icon: mdi-database
|
||||
widget:
|
||||
type: docker
|
||||
container: changemakerlite-nocodb-1
|
||||
server: my-docker
|
||||
- Gitea:
|
||||
href: "http://localhost:3030"
|
||||
# href: "https://cmlite.org" # Uncomment for public access
|
||||
description: Git repository hosting
|
||||
icon: mdi-git
|
||||
widget:
|
||||
type: docker
|
||||
container: gitea_changemaker
|
||||
server: my-docker
|
||||
href: "https://db.cmlite.org"
|
||||
description: No-code database platform
|
||||
container: changemakerlite-nocodb-1
|
||||
|
||||
- Map Server:
|
||||
icon: mdi-map
|
||||
href: "https://map.cmlite.org"
|
||||
description: Map server for geospatial data
|
||||
container: nocodb-map-viewer
|
||||
|
||||
|
||||
- Content & Documentation:
|
||||
- MkDocs (Live):
|
||||
href: "http://localhost:4000"
|
||||
# href: "https://cmlite.org" # Uncomment for public access
|
||||
description: Live documentation server with hot reload
|
||||
icon: mdi-book-open-page-variant
|
||||
widget:
|
||||
type: docker
|
||||
container: mkdocs-changemaker
|
||||
server: my-docker
|
||||
- Static Site:
|
||||
href: "http://localhost:4001"
|
||||
# href: "https://cmlite.org" # Uncomment for public access
|
||||
description: Built documentation hosting
|
||||
- Main Site:
|
||||
icon: mdi-web
|
||||
widget:
|
||||
type: docker
|
||||
container: mkdocs-site-server-changemaker
|
||||
server: my-docker
|
||||
href: "https://cmlite.org"
|
||||
description: CM-lite campaign website
|
||||
container: mkdocs-site-server-changemaker
|
||||
|
||||
- MkDocs (Live):
|
||||
icon: mdi-book-open-page-variant
|
||||
href: "https://docs.cmlite.org"
|
||||
description: Live documentation server with hot reload
|
||||
container: mkdocs-changemaker
|
||||
|
||||
- Mini QR:
|
||||
icon: mdi-qrcode
|
||||
href: "https://qr.cmlite.org"
|
||||
description: QR code generator
|
||||
container: mini-qr
|
||||
|
||||
|
||||
- Automation & Infrastructure:
|
||||
- n8n:
|
||||
href: "http://localhost:5678"
|
||||
# href: "https://cmlite.org" # Uncomment for public access
|
||||
icon: mdi-robot-industrial
|
||||
href: "https://n8n.cmlite.org"
|
||||
description: Workflow automation platform
|
||||
icon: mdi-workflow
|
||||
widget:
|
||||
type: docker
|
||||
container: n8n-changemaker
|
||||
server: my-docker
|
||||
container: n8n-changemaker
|
||||
|
||||
- PostgreSQL (Listmonk):
|
||||
icon: mdi-database-outline
|
||||
href: "#"
|
||||
description: Database for Listmonk
|
||||
icon: mdi-database-outline
|
||||
widget:
|
||||
type: docker
|
||||
container: listmonk_db
|
||||
server: my-docker
|
||||
container: listmonk_db
|
||||
|
||||
- PostgreSQL (NocoDB):
|
||||
icon: mdi-database-outline
|
||||
href: "#"
|
||||
description: Database for NocoDB
|
||||
icon: mdi-database-outline
|
||||
widget:
|
||||
type: docker
|
||||
container: changemakerlite-root_db-1
|
||||
server: my-docker
|
||||
container: changemakerlite-root_db-1
|
||||
|
||||
- Gitea:
|
||||
icon: mdi-git
|
||||
href: "https://git.cmlite.org"
|
||||
description: Git repository hosting
|
||||
container: gitea_changemaker
|
||||
@ -1,87 +0,0 @@
|
||||
---
|
||||
# For public access, replace "http://localhost" with your subdomain URLs
|
||||
|
||||
- Essential Tools:
|
||||
- Code Server:
|
||||
href: "http://localhost:8888"
|
||||
# href: "https://code.albertademocracytaskforce.org" # Uncomment for public access
|
||||
description: VS Code in the browser
|
||||
icon: mdi-code-braces
|
||||
widget:
|
||||
type: docker
|
||||
container: code-server-changemaker
|
||||
server: my-docker
|
||||
- Listmonk:
|
||||
href: "http://localhost:9000"
|
||||
# href: "https://listmonk.albertademocracytaskforce.org" # Uncomment for public access
|
||||
description: Newsletter & mailing list manager
|
||||
icon: mdi-email-newsletter
|
||||
widget:
|
||||
type: docker
|
||||
container: listmonk_app
|
||||
server: my-docker
|
||||
- NocoDB:
|
||||
href: "http://localhost:8090"
|
||||
# href: "https://db.albertademocracytaskforce.org" # Uncomment for public access
|
||||
description: No-code database platform
|
||||
icon: mdi-database
|
||||
widget:
|
||||
type: docker
|
||||
container: changemakerlite-nocodb-1
|
||||
server: my-docker
|
||||
- Gitea:
|
||||
href: "http://localhost:3030"
|
||||
# href: "https://git.albertademocracytaskforce.org" # Uncomment for public access
|
||||
description: Git repository hosting
|
||||
icon: mdi-git
|
||||
widget:
|
||||
type: docker
|
||||
container: gitea_changemaker
|
||||
server: my-docker
|
||||
|
||||
- Content & Documentation:
|
||||
- MkDocs (Live):
|
||||
href: "http://localhost:4000"
|
||||
# href: "https://docs.albertademocracytaskforce.org" # Uncomment for public access
|
||||
description: Live documentation server with hot reload
|
||||
icon: mdi-book-open-page-variant
|
||||
widget:
|
||||
type: docker
|
||||
container: mkdocs-changemaker
|
||||
server: my-docker
|
||||
- Static Site:
|
||||
href: "http://localhost:4001"
|
||||
# href: "https://albertademocracytaskforce.org" # Uncomment for public access
|
||||
description: Built documentation hosting
|
||||
icon: mdi-web
|
||||
widget:
|
||||
type: docker
|
||||
container: mkdocs-site-server-changemaker
|
||||
server: my-docker
|
||||
|
||||
- Automation & Infrastructure:
|
||||
- n8n:
|
||||
href: "http://localhost:5678"
|
||||
# href: "https://n8n.albertademocracytaskforce.org" # Uncomment for public access
|
||||
description: Workflow automation platform
|
||||
icon: mdi-workflow
|
||||
widget:
|
||||
type: docker
|
||||
container: n8n-changemaker
|
||||
server: my-docker
|
||||
- PostgreSQL (Listmonk):
|
||||
href: "#"
|
||||
description: Database for Listmonk
|
||||
icon: mdi-database-outline
|
||||
widget:
|
||||
type: docker
|
||||
container: listmonk_db
|
||||
server: my-docker
|
||||
- PostgreSQL (NocoDB):
|
||||
href: "#"
|
||||
description: Database for NocoDB
|
||||
icon: mdi-database-outline
|
||||
widget:
|
||||
type: docker
|
||||
container: changemakerlite-root_db-1
|
||||
server: my-docker
|
||||
@ -1,87 +0,0 @@
|
||||
---
|
||||
# For public access, replace "http://localhost" with your subdomain URLs
|
||||
|
||||
- Essential Tools:
|
||||
- Code Server:
|
||||
href: "http://localhost:8888"
|
||||
# href: "https://code.albertademocracytaskforce.org" # Uncomment for public access
|
||||
description: VS Code in the browser
|
||||
icon: mdi-code-braces
|
||||
widget:
|
||||
type: docker
|
||||
container: code-server-changemaker
|
||||
server: my-docker
|
||||
- Listmonk:
|
||||
href: "http://localhost:9000"
|
||||
# href: "https://listmonk.albertademocracytaskforce.org" # Uncomment for public access
|
||||
description: Newsletter & mailing list manager
|
||||
icon: mdi-email-newsletter
|
||||
widget:
|
||||
type: docker
|
||||
container: listmonk_app
|
||||
server: my-docker
|
||||
- NocoDB:
|
||||
href: "http://localhost:8090"
|
||||
# href: "https://db.albertademocracytaskforce.org" # Uncomment for public access
|
||||
description: No-code database platform
|
||||
icon: mdi-database
|
||||
widget:
|
||||
type: docker
|
||||
container: changemakerlite-nocodb-1
|
||||
server: my-docker
|
||||
- Gitea:
|
||||
href: "http://localhost:3030"
|
||||
# href: "https://git.albertademocracytaskforce.org" # Uncomment for public access
|
||||
description: Git repository hosting
|
||||
icon: mdi-git
|
||||
widget:
|
||||
type: docker
|
||||
container: gitea_changemaker
|
||||
server: my-docker
|
||||
|
||||
- Content & Documentation:
|
||||
- MkDocs (Live):
|
||||
href: "http://localhost:4000"
|
||||
# href: "https://docs.albertademocracytaskforce.org" # Uncomment for public access
|
||||
description: Live documentation server with hot reload
|
||||
icon: mdi-book-open-page-variant
|
||||
widget:
|
||||
type: docker
|
||||
container: mkdocs-changemaker
|
||||
server: my-docker
|
||||
- Static Site:
|
||||
href: "http://localhost:4001"
|
||||
# href: "https://albertademocracytaskforce.org" # Uncomment for public access
|
||||
description: Built documentation hosting
|
||||
icon: mdi-web
|
||||
widget:
|
||||
type: docker
|
||||
container: mkdocs-site-server-changemaker
|
||||
server: my-docker
|
||||
|
||||
- Automation & Infrastructure:
|
||||
- n8n:
|
||||
href: "http://localhost:5678"
|
||||
# href: "https://n8n.albertademocracytaskforce.org" # Uncomment for public access
|
||||
description: Workflow automation platform
|
||||
icon: mdi-workflow
|
||||
widget:
|
||||
type: docker
|
||||
container: n8n-changemaker
|
||||
server: my-docker
|
||||
- PostgreSQL (Listmonk):
|
||||
href: "#"
|
||||
description: Database for Listmonk
|
||||
icon: mdi-database-outline
|
||||
widget:
|
||||
type: docker
|
||||
container: listmonk_db
|
||||
server: my-docker
|
||||
- PostgreSQL (NocoDB):
|
||||
href: "#"
|
||||
description: Database for NocoDB
|
||||
icon: mdi-database-outline
|
||||
widget:
|
||||
type: docker
|
||||
container: changemakerlite-root_db-1
|
||||
server: my-docker
|
||||
@ -21,6 +21,15 @@ layout:
|
||||
style: columns
|
||||
columns: 3
|
||||
|
||||
docker:
|
||||
widget:
|
||||
# Set this to false to hide CPU, memory, and network stats
|
||||
showStats: false
|
||||
|
||||
# You can still keep health indicators
|
||||
showHealth: true
|
||||
|
||||
|
||||
quicklaunch:
|
||||
searchDescriptions: true
|
||||
hideInternetSearch: true
|
||||
|
||||
@ -7,6 +7,16 @@
|
||||
memory: true
|
||||
disk: /
|
||||
|
||||
- openmeteo:
|
||||
label: Edmonton # optional
|
||||
latitude: 53.5461
|
||||
longitude: -113.4938
|
||||
timezone: America/Edmonton # optional
|
||||
units: metric # or imperial
|
||||
cache: 5 # Time in minutes to cache API responses, to stay within limits
|
||||
format: # optional, Intl.NumberFormat options
|
||||
maximumFractionDigits: 1
|
||||
|
||||
- greeting:
|
||||
text_size: xl
|
||||
text: "Welcome to Changemaker Lite"
|
||||
@ -21,7 +31,3 @@
|
||||
- search:
|
||||
provider: duckduckgo
|
||||
target: _blank
|
||||
|
||||
- unifi_console:
|
||||
text_size: md
|
||||
text: "Services Available: Code Server, Listmonk, NocoDB, MkDocs, n8n, Gitea"
|
||||
|
||||
@ -230,25 +230,14 @@ services:
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
|
||||
# Cloudflare Tunnel (uncommented by start-production.sh)
|
||||
# cloudflared:
|
||||
# image: cloudflare/cloudflared:latest
|
||||
# container_name: cloudflared-changemaker
|
||||
# restart: unless-stopped
|
||||
# command: tunnel run
|
||||
# environment:
|
||||
# - TUNNEL_TOKEN=${CF_TUNNEL_TOKEN}
|
||||
# networks:
|
||||
# - changemaker-lite
|
||||
# depends_on:
|
||||
# - homepage-changemaker
|
||||
# - code-server
|
||||
# - listmonk-app
|
||||
# - mkdocs
|
||||
# - mkdocs-site-server
|
||||
# - n8n
|
||||
# - nocodb
|
||||
# - gitea-app
|
||||
mini-qr:
|
||||
image: ghcr.io/lyqht/mini-qr:latest
|
||||
container_name: mini-qr
|
||||
ports:
|
||||
- "${MINI_QR_PORT:-8089}:8080"
|
||||
restart: unless-stopped
|
||||
networks:
|
||||
- changemaker-lite
|
||||
|
||||
networks:
|
||||
changemaker-lite:
|
||||
|
||||
40
docs-cloudflare.md
Normal file
40
docs-cloudflare.md
Normal file
@ -0,0 +1,40 @@
|
||||
# Cloudflare Configuration Guide for Changemaker.lite
|
||||
|
||||
This guide will help you properly configure Cloudflare credentials for use with Changemaker.lite's production deployment.
|
||||
|
||||
## Finding Your Zone ID
|
||||
|
||||
The Zone ID is a unique identifier for your domain in Cloudflare.
|
||||
|
||||
1. Log in to the [Cloudflare Dashboard](https://dash.cloudflare.com)
|
||||
2. Select your domain (e.g., cmlite.org)
|
||||
3. On the right sidebar under "API", you'll see "Zone ID"
|
||||
4. Copy this value - it should look something like: `1a2b3c4d5e6f7g8h9i0j1k2l3m4n5o6p`
|
||||
|
||||
## Creating an API Token
|
||||
|
||||
You need an API token with proper permissions to manage DNS records and access policies.
|
||||
|
||||
1. Go to [Cloudflare Dashboard](https://dash.cloudflare.com) > Profile (top right) > API Tokens
|
||||
2. Click "Create Token"
|
||||
3. Use the "Edit zone DNS" template (or create a custom token)
|
||||
4. For a custom token, ensure it has the following permissions:
|
||||
- Zone - DNS - Edit
|
||||
- Zone - Settings - Read
|
||||
- Account - Cloudflare Tunnel - Read
|
||||
5. Under "Zone Resources", select "Include - Specific zone" and choose your domain
|
||||
6. Create the token and copy its value
|
||||
|
||||
## Finding Your Account ID
|
||||
|
||||
The Account ID is needed for some Cloudflare Tunnel operations.
|
||||
|
||||
1. Go to the [Cloudflare Dashboard](https://dash.cloudflare.com)
|
||||
2. Look at the URL when logged in - it will contain your account ID:
|
||||
`https://dash.cloudflare.com/1a2b3c4d5e6f7g8h9i0j/your-domain.com`
|
||||
3. The string after `/dash.cloudflare.com/` is your Account ID (e.g., `1a2b3c4d5e6f7g8h9i0j`)
|
||||
|
||||
## Updating Your .env File
|
||||
|
||||
Update your `.env` file with these values:
|
||||
|
||||
@ -25,3 +25,9 @@ services:
|
||||
options:
|
||||
max-size: "10m"
|
||||
max-file: "3"
|
||||
networks:
|
||||
- changemakerlite_changemaker-lite
|
||||
|
||||
networks:
|
||||
changemakerlite_changemaker-lite:
|
||||
external: true
|
||||
|
||||
BIN
mkdocs/.cache/plugin/social/112206e21dc1efc3b2fdcaf783b198ac.png
Normal file
BIN
mkdocs/.cache/plugin/social/112206e21dc1efc3b2fdcaf783b198ac.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 30 KiB |
@ -1,9 +0,0 @@
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block extrahead %}
|
||||
{% endblock %}
|
||||
|
||||
{% block announce %}
|
||||
<a href="https://homepage.albertademocracytaskforce.org" class="login-button">Login</a>
|
||||
Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
|
||||
{% endblock %}
|
||||
@ -1,9 +0,0 @@
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block extrahead %}
|
||||
{% endblock %}
|
||||
|
||||
{% block announce %}
|
||||
<a href="https://homepage.albertademocracytaskforce.org" class="login-button">Login</a>
|
||||
Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
|
||||
{% endblock %}
|
||||
@ -1,66 +0,0 @@
|
||||
site_name: Changemaker Lite Documentation
|
||||
site_description: Self-hosted platform for documentation and development
|
||||
site_url: https://changeme.org
|
||||
site_author: Bunker Ops
|
||||
docs_dir: docs
|
||||
site_dir: site
|
||||
|
||||
# Theme
|
||||
theme:
|
||||
name: material
|
||||
custom_dir: docs/overrides
|
||||
palette:
|
||||
scheme: slate
|
||||
primary: deep purple
|
||||
accent: amber
|
||||
features:
|
||||
- navigation.tracking
|
||||
- navigation.indexes
|
||||
- navigation.collapse
|
||||
- navigation.path
|
||||
- content.code.copy
|
||||
- navigation.top
|
||||
- navigation.tabs # Added for top-level navigation tabs
|
||||
|
||||
extra_css:
|
||||
- stylesheets/extra.css
|
||||
markdown_extensions:
|
||||
- pymdownx.highlight:
|
||||
anchor_linenums: true
|
||||
- pymdownx.superfences
|
||||
- admonition
|
||||
- pymdownx.details
|
||||
- attr_list
|
||||
- md_in_html
|
||||
- pymdownx.emoji # Simplified emoji config
|
||||
- footnotes
|
||||
- toc:
|
||||
permalink: true
|
||||
# The specific slugify line was removed to avoid previous tool error,
|
||||
# you may need to add back your preferred slugify option:
|
||||
# slugify: !!python/name:pymdownx.slugs.uslugify
|
||||
|
||||
copyright: Copyright © 2024 The Bunker Operations - Built with Change Maker
|
||||
|
||||
# Plugins
|
||||
plugins:
|
||||
- social
|
||||
- search
|
||||
- blog
|
||||
# - tags # Consider adding if you use tags for your blog or docs
|
||||
|
||||
# Navigation
|
||||
nav:
|
||||
- Home: index.md
|
||||
- Getting Started: getting-started.md
|
||||
- Services:
|
||||
- Overview: services/index.md
|
||||
- Homepage: services/homepage.md
|
||||
- Code Server: services/code-server.md
|
||||
- MkDocs Material: services/mkdocs.md
|
||||
- Static Site Server: services/static-server.md
|
||||
- Listmonk: services/listmonk.md
|
||||
- PostgreSQL: services/postgresql.md
|
||||
- n8n: services/n8n.md
|
||||
- NocoDB: services/nocodb.md
|
||||
- Blog: blog/index.md
|
||||
732
start-production.sh
Normal file → Executable file
732
start-production.sh
Normal file → Executable file
@ -2,13 +2,13 @@
|
||||
|
||||
echo "#############################################################"
|
||||
echo "# "
|
||||
echo "# Changemaker.lite Production Setup "
|
||||
echo "# Changemaker.lite Production Deployment "
|
||||
echo "# "
|
||||
echo "# This script will: "
|
||||
echo "# 1. Create a Cloudflare tunnel "
|
||||
echo "# 2. Configure DNS records "
|
||||
echo "# 3. Set up access policies "
|
||||
echo "# 4. Enable the cloudflared container "
|
||||
echo "# 1. Install and configure cloudflared "
|
||||
echo "# 2. Create a systemd service for the tunnel "
|
||||
echo "# 3. Configure DNS records "
|
||||
echo "# 4. Set up access policies "
|
||||
echo "# "
|
||||
echo "#############################################################"
|
||||
echo ""
|
||||
@ -16,7 +16,9 @@ echo ""
|
||||
# Get script directory
|
||||
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||
ENV_FILE="$SCRIPT_DIR/.env"
|
||||
DOCKER_COMPOSE_FILE="$SCRIPT_DIR/docker-compose.yml"
|
||||
TUNNEL_CONFIG_FILE="$SCRIPT_DIR/configs/cloudflare/tunnel-config.yml"
|
||||
TUNNEL_CREDS_DIR="$SCRIPT_DIR/configs/cloudflare"
|
||||
SERVICE_NAME="cloudflared-changemaker"
|
||||
|
||||
# Source environment variables
|
||||
if [ -f "$ENV_FILE" ]; then
|
||||
@ -29,191 +31,332 @@ fi
|
||||
# Check if Cloudflare credentials are properly configured
|
||||
if [ -z "$CF_API_TOKEN" ] || [ "$CF_API_TOKEN" == "your_cloudflare_api_token" ] || \
|
||||
[ -z "$CF_ZONE_ID" ] || [ "$CF_ZONE_ID" == "your_cloudflare_zone_id" ] || \
|
||||
[ -z "$CF_DOMAIN" ]; then
|
||||
echo "Error: Cloudflare credentials not properly configured in .env file."
|
||||
[ -z "$CF_DOMAIN" ] || [ -z "$CF_ACCOUNT_ID" ] || [ "$CF_ACCOUNT_ID" == "your_cloudflare_account_id" ]; then
|
||||
echo "Error: Cloudflare configuration incomplete."
|
||||
echo ""
|
||||
echo "Current values:"
|
||||
echo " CF_API_TOKEN: ${CF_API_TOKEN:-not set}"
|
||||
echo " CF_ZONE_ID: ${CF_ZONE_ID:-not set}"
|
||||
echo " CF_DOMAIN: ${CF_DOMAIN:-not set}"
|
||||
echo " CF_ACCOUNT_ID: ${CF_ACCOUNT_ID:-not set}"
|
||||
echo ""
|
||||
echo "Please run ./config.sh and configure Cloudflare settings, or manually update your .env file."
|
||||
echo "Please run ./config.sh and complete the Cloudflare configuration."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check if CF_ACCOUNT_ID exists in .env, if not prompt for it
|
||||
if [ -z "$CF_ACCOUNT_ID" ]; then
|
||||
echo "Cloudflare Account ID is required for tunnel creation."
|
||||
echo "You can find it in your Cloudflare dashboard at the top right."
|
||||
read -p "Enter your Cloudflare Account ID: " CF_ACCOUNT_ID
|
||||
|
||||
# Update .env with account ID
|
||||
echo "" >> "$ENV_FILE"
|
||||
echo "# Cloudflare Account ID (added by start-production.sh)" >> "$ENV_FILE"
|
||||
echo "CF_ACCOUNT_ID=$CF_ACCOUNT_ID" >> "$ENV_FILE"
|
||||
|
||||
# Re-export the variable
|
||||
export CF_ACCOUNT_ID
|
||||
fi
|
||||
|
||||
# Check if required variables are set
|
||||
if [ -z "$CF_API_TOKEN" ] || [ -z "$CF_ZONE_ID" ] || [ -z "$CF_DOMAIN" ]; then
|
||||
echo "Error: Cloudflare credentials not found in .env file."
|
||||
echo "Please run ./config.sh and configure Cloudflare settings."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check if services are running
|
||||
echo "Checking if services are running..."
|
||||
if ! docker compose ps | grep -q "Up"; then
|
||||
echo "Error: No services are running. Please run 'docker compose up -d' first."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "✓ Services are running"
|
||||
echo ""
|
||||
|
||||
# Show current service URLs
|
||||
echo "Current local service URLs:"
|
||||
echo " - Homepage: http://localhost:${HOMEPAGE_PORT:-3010}"
|
||||
echo " - Code Server: http://localhost:${CODE_SERVER_PORT:-8888}"
|
||||
echo " - Listmonk: http://localhost:${LISTMONK_PORT:-9000}"
|
||||
echo " - Documentation (Dev): http://localhost:${MKDOCS_PORT:-4000}"
|
||||
echo " - Documentation (Built): http://localhost:${MKDOCS_SITE_SERVER_PORT:-4001}"
|
||||
echo " - n8n: http://localhost:${N8N_PORT:-5678}"
|
||||
echo " - NocoDB: http://localhost:${NOCODB_PORT:-8090}"
|
||||
echo " - Gitea: http://localhost:${GITEA_WEB_PORT:-3030}"
|
||||
echo ""
|
||||
|
||||
read -p "Have you tested all services locally and are ready to go to production? (yes/no): " confirm
|
||||
if [[ "$confirm" != "yes" ]]; then
|
||||
echo "Please test all services locally before running production setup."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "Starting production setup..."
|
||||
|
||||
# Install jq if not present
|
||||
if ! command -v jq &> /dev/null; then
|
||||
echo "Installing jq..."
|
||||
sudo apt-get update && sudo apt-get install -y jq
|
||||
fi
|
||||
|
||||
# Create Cloudflare tunnel
|
||||
echo ""
|
||||
echo "Creating Cloudflare tunnel..."
|
||||
|
||||
TUNNEL_NAME="changemaker-${HOSTNAME}-$(date +%s)"
|
||||
|
||||
# Create tunnel via API
|
||||
TUNNEL_RESPONSE=$(curl -s -X POST "https://api.cloudflare.com/client/v4/accounts/${CF_ACCOUNT_ID}/cfd_tunnel" \
|
||||
-H "Authorization: Bearer $CF_API_TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
--data "{\"name\":\"$TUNNEL_NAME\",\"config_src\":\"cloudflare\"}")
|
||||
|
||||
# Check if we need account ID
|
||||
if echo "$TUNNEL_RESPONSE" | jq -e '.errors[] | select(.code == 0)' > /dev/null 2>&1; then
|
||||
echo ""
|
||||
echo "Account ID is required. You can find it in your Cloudflare dashboard."
|
||||
read -p "Enter your Cloudflare Account ID: " CF_ACCOUNT_ID
|
||||
|
||||
# Update .env with account ID
|
||||
if grep -q "^CF_ACCOUNT_ID=" "$ENV_FILE"; then
|
||||
sed -i "s/^CF_ACCOUNT_ID=.*/CF_ACCOUNT_ID=$CF_ACCOUNT_ID/" "$ENV_FILE"
|
||||
# Check if cloudflared is installed
|
||||
check_cloudflared() {
|
||||
if ! command -v cloudflared &> /dev/null; then
|
||||
echo "cloudflared not found. Installing..."
|
||||
install_cloudflared
|
||||
else
|
||||
echo "CF_ACCOUNT_ID=$CF_ACCOUNT_ID" >> "$ENV_FILE"
|
||||
echo "✅ cloudflared is already installed: $(cloudflared --version | head -n1)"
|
||||
fi
|
||||
}
|
||||
|
||||
# Install cloudflared
|
||||
install_cloudflared() {
|
||||
echo "Installing cloudflared..."
|
||||
|
||||
# Check if we need to add the Cloudflare repository
|
||||
if [ ! -f /usr/share/keyrings/cloudflare-main.gpg ]; then
|
||||
# Add the cloudflare gpg key
|
||||
curl -fsSL https://pkg.cloudflare.com/cloudflare-main.gpg | sudo gpg --dearmor -o /usr/share/keyrings/cloudflare-main.gpg
|
||||
|
||||
# Add the repository
|
||||
echo "deb [signed-by=/usr/share/keyrings/cloudflare-main.gpg] https://pkg.cloudflare.com/cloudflared $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/cloudflared.list
|
||||
fi
|
||||
|
||||
# Retry with account ID
|
||||
TUNNEL_RESPONSE=$(curl -s -X POST "https://api.cloudflare.com/client/v4/accounts/$CF_ACCOUNT_ID/cfd_tunnel" \
|
||||
-H "Authorization: Bearer $CF_API_TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
--data "{\"name\":\"$TUNNEL_NAME\",\"config_src\":\"cloudflare\"}")
|
||||
fi
|
||||
# Update and install
|
||||
sudo apt-get update && sudo apt-get install -y cloudflared
|
||||
|
||||
TUNNEL_ID=$(echo "$TUNNEL_RESPONSE" | jq -r '.result.id')
|
||||
TUNNEL_TOKEN=$(echo "$TUNNEL_RESPONSE" | jq -r '.result.token')
|
||||
|
||||
if [ -z "$TUNNEL_ID" ] || [ "$TUNNEL_ID" == "null" ]; then
|
||||
echo "Error: Failed to create tunnel"
|
||||
echo "$TUNNEL_RESPONSE" | jq .
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "✓ Created tunnel: $TUNNEL_NAME (ID: $TUNNEL_ID)"
|
||||
|
||||
# Update .env with tunnel information
|
||||
echo "CF_TUNNEL_ID=$TUNNEL_ID" >> "$ENV_FILE"
|
||||
echo "CF_TUNNEL_TOKEN=$TUNNEL_TOKEN" >> "$ENV_FILE"
|
||||
echo "CF_TUNNEL_NAME=$TUNNEL_NAME" >> "$ENV_FILE"
|
||||
|
||||
# Configure tunnel routes
|
||||
echo ""
|
||||
echo "Configuring tunnel routes..."
|
||||
|
||||
# Define services and their configurations
|
||||
declare -A SERVICES=(
|
||||
["dashboard"]="homepage-changemaker:3000"
|
||||
["code"]="code-server:8080"
|
||||
["listmonk"]="listmonk-app:9000"
|
||||
["docs"]="mkdocs:8000"
|
||||
["n8n"]="n8n:5678"
|
||||
["db"]="nocodb:8080"
|
||||
["git"]="gitea-app:3000"
|
||||
)
|
||||
|
||||
# Configure root domain to mkdocs-site-server
|
||||
echo "Configuring route for root domain..."
|
||||
ROOT_CONFIG=$(cat <<EOF
|
||||
{
|
||||
"tunnel_id": "$TUNNEL_ID",
|
||||
"hostname": "$CF_DOMAIN",
|
||||
"service": "http://mkdocs-site-server:80"
|
||||
if ! command -v cloudflared &> /dev/null; then
|
||||
echo "Failed to install cloudflared. Please install it manually following the instructions at:"
|
||||
echo "https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/downloads/"
|
||||
exit 1
|
||||
else
|
||||
echo "✅ cloudflared installed successfully: $(cloudflared --version | head -n1)"
|
||||
fi
|
||||
}
|
||||
EOF
|
||||
)
|
||||
|
||||
ROOT_RESPONSE=$(curl -s -X PUT "https://api.cloudflare.com/client/v4/zones/$CF_ZONE_ID/tunnels/$TUNNEL_ID/configurations" \
|
||||
-H "Authorization: Bearer $CF_API_TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
--data "$ROOT_CONFIG")
|
||||
# Authenticate with Cloudflare
|
||||
authenticate_cloudflare() {
|
||||
echo "Checking Cloudflare authentication..."
|
||||
|
||||
# Configure subdomain routes
|
||||
for subdomain in "${!SERVICES[@]}"; do
|
||||
service="${SERVICES[$subdomain]}"
|
||||
echo "Configuring route for $subdomain.$CF_DOMAIN -> $service"
|
||||
# Remove --account-tag parameter as it's not supported in this version
|
||||
if ! cloudflared tunnel list &> /dev/null; then
|
||||
echo "Not authenticated with Cloudflare. Starting authentication process..."
|
||||
echo "Log in to Cloudflare in the browser window that opens..."
|
||||
|
||||
CONFIG=$(cat <<EOF
|
||||
{
|
||||
"tunnel_id": "$TUNNEL_ID",
|
||||
"hostname": "$subdomain.$CF_DOMAIN",
|
||||
"service": "http://$service"
|
||||
# Run login
|
||||
if ! cloudflared tunnel login; then
|
||||
echo "Authentication failed. Please try again or authenticate manually using:"
|
||||
echo "cloudflared tunnel login"
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
echo "✅ Already authenticated with Cloudflare"
|
||||
fi
|
||||
}
|
||||
EOF
|
||||
)
|
||||
|
||||
RESPONSE=$(curl -s -X PUT "https://api.cloudflare.com/client/v4/zones/$CF_ZONE_ID/tunnels/$TUNNEL_ID/configurations" \
|
||||
-H "Authorization: Bearer $CF_API_TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
--data "$CONFIG")
|
||||
done
|
||||
# Create or get existing tunnel
|
||||
setup_tunnel() {
|
||||
echo "Setting up Cloudflare tunnel..."
|
||||
|
||||
# Create DNS records
|
||||
echo ""
|
||||
echo "Creating DNS records..."
|
||||
# Check if we have a tunnel ID in the environment
|
||||
local tunnel_name="changemaker-lite"
|
||||
local tunnel_id=""
|
||||
|
||||
# Check if tunnel exists by name
|
||||
echo "Checking for existing tunnel named '$tunnel_name'..."
|
||||
local tunnel_list_output
|
||||
# Remove --account-tag parameter as it's not supported in this version
|
||||
tunnel_list_output=$(cloudflared tunnel list --output json 2>&1)
|
||||
|
||||
# Check if the command was successful
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "Error listing tunnels: $tunnel_list_output"
|
||||
echo "Please ensure you're properly authenticated."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Fix for invalid JSON output - try to clean the output if needed
|
||||
if ! echo "$tunnel_list_output" | jq '.' &>/dev/null; then
|
||||
echo "Warning: Invalid JSON returned from cloudflared. Attempting to clean output..."
|
||||
# Try to extract valid JSON portion
|
||||
tunnel_list_output=$(echo "$tunnel_list_output" | grep -o '\[.*\]' || echo "[]")
|
||||
fi
|
||||
|
||||
# Now try to extract the tunnel info
|
||||
local tunnel_info
|
||||
if echo "$tunnel_list_output" | jq '.' &>/dev/null; then
|
||||
tunnel_info=$(echo "$tunnel_list_output" | jq -r '.[] | select(.name=="'$tunnel_name'")' 2>/dev/null || echo "")
|
||||
else
|
||||
echo "Failed to parse tunnel list. Cannot check for existing tunnels."
|
||||
tunnel_info=""
|
||||
fi
|
||||
|
||||
if [ -n "$tunnel_info" ]; then
|
||||
# Tunnel exists
|
||||
tunnel_id=$(echo "$tunnel_info" | jq -r '.id' 2>/dev/null)
|
||||
if [ -n "$tunnel_id" ] && [ "$tunnel_id" != "null" ]; then
|
||||
echo "✅ Found existing tunnel: $tunnel_name (ID: $tunnel_id)"
|
||||
|
||||
# Update the environment variable if needed
|
||||
if [ "$CF_TUNNEL_ID" != "$tunnel_id" ]; then
|
||||
echo "Updating CF_TUNNEL_ID in .env file..."
|
||||
sed -i "s/CF_TUNNEL_ID=.*/CF_TUNNEL_ID=$tunnel_id/" "$ENV_FILE"
|
||||
# Reload the variable
|
||||
export CF_TUNNEL_ID="$tunnel_id"
|
||||
fi
|
||||
else
|
||||
echo "Warning: Found tunnel but couldn't extract ID"
|
||||
fi
|
||||
else
|
||||
# Create new tunnel
|
||||
echo "Creating new tunnel: $tunnel_name"
|
||||
local tunnel_create_output
|
||||
# Remove --account-tag parameter as it's not supported in this version
|
||||
tunnel_create_output=$(cloudflared tunnel create "$tunnel_name" 2>&1)
|
||||
echo "Tunnel creation output:"
|
||||
echo "$tunnel_create_output"
|
||||
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "Failed to create tunnel. Please check your Cloudflare credentials."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Try multiple methods to extract the tunnel ID from output
|
||||
# Method 1: Try the original regex pattern
|
||||
tunnel_id=$(echo "$tunnel_create_output" | grep -oP 'Created tunnel changemaker-lite with id \K[a-f0-9-]+' || echo "")
|
||||
|
||||
# Method 2: Look for UUID pattern
|
||||
if [ -z "$tunnel_id" ]; then
|
||||
tunnel_id=$(echo "$tunnel_create_output" | grep -oP '[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}' || echo "")
|
||||
fi
|
||||
|
||||
# Method 3: Look for hex string that might be the ID
|
||||
if [ -z "$tunnel_id" ]; then
|
||||
tunnel_id=$(echo "$tunnel_create_output" | grep -oP '\b[a-f0-9-]{20,}\b' || echo "")
|
||||
fi
|
||||
|
||||
# Interactive method as fallback
|
||||
if [ -z "$tunnel_id" ]; then
|
||||
echo "Could not automatically extract tunnel ID from output."
|
||||
echo "Please check the output above and enter the tunnel ID manually:"
|
||||
read -p "Tunnel ID: " tunnel_id
|
||||
|
||||
if [ -z "$tunnel_id" ]; then
|
||||
echo "No tunnel ID provided. Please create the tunnel manually and set CF_TUNNEL_ID in the .env file."
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
echo "✅ Created new tunnel: $tunnel_name (ID: $tunnel_id)"
|
||||
|
||||
# Update the environment variable
|
||||
sed -i "s/CF_TUNNEL_ID=.*/CF_TUNNEL_ID=$tunnel_id/" "$ENV_FILE"
|
||||
export CF_TUNNEL_ID="$tunnel_id"
|
||||
fi
|
||||
|
||||
# Make sure credentials directory exists
|
||||
mkdir -p "$TUNNEL_CREDS_DIR"
|
||||
|
||||
# Check if we need to copy the credentials file
|
||||
local creds_file="$HOME/.cloudflared/$tunnel_id.json"
|
||||
local target_creds_file="$TUNNEL_CREDS_DIR/$tunnel_id.json"
|
||||
|
||||
if [ -f "$creds_file" ] && [ ! -f "$target_creds_file" ]; then
|
||||
echo "Copying tunnel credentials to project directory..."
|
||||
cp "$creds_file" "$target_creds_file"
|
||||
echo "✅ Credentials copied to $target_creds_file"
|
||||
elif [ ! -f "$creds_file" ]; then
|
||||
echo "Warning: Tunnel credentials not found at $creds_file"
|
||||
echo "Checking for credentials in alternative locations..."
|
||||
|
||||
# Try to find credentials in ~/.cloudflared directory
|
||||
local found_creds=false
|
||||
for cred_file in "$HOME/.cloudflared/"*.json; do
|
||||
if [ -f "$cred_file" ]; then
|
||||
echo "Found credentials file: $cred_file"
|
||||
echo "Checking if this file contains credentials for our tunnel..."
|
||||
|
||||
# Check if the file contains the tunnel ID
|
||||
if grep -q "$tunnel_id" "$cred_file"; then
|
||||
echo "✅ This appears to be the correct credentials file!"
|
||||
cp "$cred_file" "$target_creds_file"
|
||||
echo "✅ Credentials copied to $target_creds_file"
|
||||
found_creds=true
|
||||
break
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
if [ "$found_creds" = false ]; then
|
||||
echo "Error: Could not find tunnel credentials."
|
||||
echo "Please locate the credentials file for tunnel $tunnel_id and copy it to:"
|
||||
echo "$target_creds_file"
|
||||
echo ""
|
||||
echo "You can also run this command manually to create a new tunnel with credentials:"
|
||||
echo "cloudflared tunnel create --account-tag \"$CF_ACCOUNT_ID\" \"$tunnel_name\""
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
# Update tunnel configuration file
|
||||
update_tunnel_config "$target_creds_file"
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
# Update tunnel configuration
|
||||
update_tunnel_config() {
|
||||
local creds_file="$1"
|
||||
|
||||
echo "Updating tunnel configuration..."
|
||||
|
||||
# Create or update the config file
|
||||
cat > "$TUNNEL_CONFIG_FILE" << EOL
|
||||
# Cloudflare Tunnel Configuration for $CF_DOMAIN
|
||||
# Generated by Changemaker.lite start-production.sh on $(date)
|
||||
|
||||
tunnel: ${CF_TUNNEL_ID}
|
||||
credentials-file: ${creds_file}
|
||||
ingress:
|
||||
- hostname: homepage.${CF_DOMAIN}
|
||||
service: http://localhost:${HOMEPAGE_PORT:-3010}
|
||||
- hostname: code.${CF_DOMAIN}
|
||||
service: http://localhost:${CODE_SERVER_PORT:-8888}
|
||||
- hostname: listmonk.${CF_DOMAIN}
|
||||
service: http://localhost:${LISTMONK_PORT:-9000}
|
||||
- hostname: docs.${CF_DOMAIN}
|
||||
service: http://localhost:${MKDOCS_PORT:-4000}
|
||||
- hostname: ${CF_DOMAIN}
|
||||
service: http://localhost:${MKDOCS_SITE_SERVER_PORT:-4001}
|
||||
- hostname: n8n.${CF_DOMAIN}
|
||||
service: http://localhost:${N8N_PORT:-5678}
|
||||
- hostname: db.${CF_DOMAIN}
|
||||
service: http://localhost:${NOCODB_PORT:-8090}
|
||||
- hostname: git.${CF_DOMAIN}
|
||||
service: http://localhost:${GITEA_WEB_PORT:-3030}
|
||||
- hostname: map.${CF_DOMAIN}
|
||||
service: http://localhost:${MAP_PORT:-3000}
|
||||
- hostname: qr.${CF_DOMAIN}
|
||||
service: http://localhost:${MINI_QR_PORT:-8089}
|
||||
- service: http_status:404
|
||||
EOL
|
||||
|
||||
echo "✅ Tunnel configuration updated at $TUNNEL_CONFIG_FILE"
|
||||
}
|
||||
|
||||
# Create systemd service for cloudflared
|
||||
create_systemd_service() {
|
||||
echo "Creating systemd service for cloudflared tunnel..."
|
||||
|
||||
local cloudflared_path=$(which cloudflared)
|
||||
local username=$(whoami)
|
||||
|
||||
# Create service file content
|
||||
local service_content="[Unit]
|
||||
Description=Cloudflare Tunnel for Changemaker.lite
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
User=$username
|
||||
ExecStart=$cloudflared_path tunnel --config $TUNNEL_CONFIG_FILE run
|
||||
Restart=always
|
||||
RestartSec=5
|
||||
StartLimitInterval=0
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target"
|
||||
|
||||
# Write service file
|
||||
echo "$service_content" | sudo tee /etc/systemd/system/$SERVICE_NAME.service > /dev/null
|
||||
|
||||
# Reload systemd
|
||||
sudo systemctl daemon-reload
|
||||
|
||||
# Enable and start the service
|
||||
sudo systemctl enable $SERVICE_NAME.service
|
||||
sudo systemctl restart $SERVICE_NAME.service
|
||||
|
||||
# Check service status
|
||||
sleep 3
|
||||
if sudo systemctl is-active --quiet $SERVICE_NAME.service; then
|
||||
echo "✅ Cloudflared service is running"
|
||||
else
|
||||
echo "⚠️ Cloudflared service failed to start. Checking logs..."
|
||||
sudo systemctl status $SERVICE_NAME.service
|
||||
echo "Viewing recent logs:"
|
||||
sudo journalctl -u $SERVICE_NAME.service --no-pager -n 20
|
||||
|
||||
echo "Please check the configuration and try again."
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Function to create/update DNS record
|
||||
create_dns_record() {
|
||||
local name=$1
|
||||
local content="$TUNNEL_ID.cfargotunnel.com"
|
||||
local full_name
|
||||
local content="$CF_TUNNEL_ID.cfargotunnel.com"
|
||||
|
||||
# Determine the full DNS name
|
||||
if [ "$name" == "@" ]; then
|
||||
full_name="$CF_DOMAIN"
|
||||
else
|
||||
full_name="$name.$CF_DOMAIN"
|
||||
fi
|
||||
|
||||
echo "Configuring DNS record for $full_name..."
|
||||
|
||||
# Check if record exists
|
||||
EXISTING=$(curl -s -X GET "https://api.cloudflare.com/client/v4/zones/$CF_ZONE_ID/dns_records?name=$name.$CF_DOMAIN&type=CNAME" \
|
||||
EXISTING=$(curl -s -X GET "https://api.cloudflare.com/client/v4/zones/$CF_ZONE_ID/dns_records?name=$full_name" \
|
||||
-H "Authorization: Bearer $CF_API_TOKEN" \
|
||||
-H "Content-Type: application/json")
|
||||
|
||||
RECORD_ID=$(echo "$EXISTING" | jq -r '.result[0].id')
|
||||
RECORD_ID=$(echo "$EXISTING" | jq -r '.result[] | select(.name == "'$full_name'") | .id' | head -1)
|
||||
|
||||
if [ ! -z "$RECORD_ID" ] && [ "$RECORD_ID" != "null" ]; then
|
||||
# Update existing record
|
||||
@ -242,80 +385,215 @@ create_dns_record() {
|
||||
fi
|
||||
|
||||
if echo "$RESPONSE" | jq -e '.success' > /dev/null; then
|
||||
echo "✓ DNS record for $name.$CF_DOMAIN configured"
|
||||
echo " ✅ DNS record configured"
|
||||
else
|
||||
echo "✗ Failed to configure DNS record for $name.$CF_DOMAIN"
|
||||
echo " ❌ Failed to configure DNS record"
|
||||
echo "$RESPONSE" | jq '.errors'
|
||||
fi
|
||||
}
|
||||
|
||||
# Create DNS records for all subdomains
|
||||
for subdomain in "${!SERVICES[@]}"; do
|
||||
create_dns_record "$subdomain"
|
||||
done
|
||||
|
||||
# Create root domain record
|
||||
create_dns_record "@"
|
||||
|
||||
# Set up access policies
|
||||
echo ""
|
||||
echo "Setting up access policies..."
|
||||
read -p "Enter admin email for protected services (dashboard, code): " ADMIN_EMAIL
|
||||
setup_access_policies() {
|
||||
echo ""
|
||||
echo "Setting up Cloudflare Access policies..."
|
||||
read -p "Enter email address for admin access to protected services: " ADMIN_EMAIL
|
||||
|
||||
if [[ "$ADMIN_EMAIL" =~ ^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$ ]]; then
|
||||
# Create access applications for protected services
|
||||
PROTECTED_SERVICES=("dashboard" "code")
|
||||
if [[ "$ADMIN_EMAIL" =~ ^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$ ]]; then
|
||||
# Protected services
|
||||
PROTECTED_SERVICES=("homepage" "code")
|
||||
|
||||
for service in "${PROTECTED_SERVICES[@]}"; do
|
||||
echo "Creating access policy for $service.$CF_DOMAIN..."
|
||||
for service in "${PROTECTED_SERVICES[@]}"; do
|
||||
echo "Creating access policy for $service.$CF_DOMAIN..."
|
||||
|
||||
# Create access application
|
||||
APP_RESPONSE=$(curl -s -X POST "https://api.cloudflare.com/client/v4/zones/$CF_ZONE_ID/access/apps" \
|
||||
-H "Authorization: Bearer $CF_API_TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
--data "{
|
||||
\"name\": \"$service.$CF_DOMAIN\",
|
||||
\"domain\": \"$service.$CF_DOMAIN\",
|
||||
\"type\": \"self_hosted\",
|
||||
\"session_duration\": \"24h\"
|
||||
}")
|
||||
|
||||
APP_ID=$(echo "$APP_RESPONSE" | jq -r '.result.id')
|
||||
|
||||
if [ ! -z "$APP_ID" ] && [ "$APP_ID" != "null" ]; then
|
||||
# Create policy
|
||||
POLICY_RESPONSE=$(curl -s -X POST "https://api.cloudflare.com/client/v4/zones/$CF_ZONE_ID/access/apps/$APP_ID/policies" \
|
||||
# Check if application already exists
|
||||
EXISTING_APPS=$(curl -s -X GET "https://api.cloudflare.com/client/v4/zones/$CF_ZONE_ID/access/apps" \
|
||||
-H "Authorization: Bearer $CF_API_TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
--data "{
|
||||
\"name\": \"Email Policy\",
|
||||
\"decision\": \"allow\",
|
||||
\"include\": [{
|
||||
\"email\": {\"email\": \"$ADMIN_EMAIL\"}
|
||||
}]
|
||||
}")
|
||||
-H "Content-Type: application/json")
|
||||
|
||||
echo "✓ Access policy created for $service.$CF_DOMAIN"
|
||||
APP_ID=$(echo "$EXISTING_APPS" | jq -r ".result[] | select(.domain == \"$service.$CF_DOMAIN\") | .id" | head -1)
|
||||
|
||||
if [ -z "$APP_ID" ] || [ "$APP_ID" == "null" ]; then
|
||||
# Create new access application
|
||||
APP_RESPONSE=$(curl -s -X POST "https://api.cloudflare.com/client/v4/zones/$CF_ZONE_ID/access/apps" \
|
||||
-H "Authorization: Bearer $CF_API_TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
--data "{
|
||||
\"name\": \"$service.$CF_DOMAIN\",
|
||||
\"domain\": \"$service.$CF_DOMAIN\",
|
||||
\"type\": \"self_hosted\",
|
||||
\"session_duration\": \"24h\",
|
||||
\"auto_redirect_to_identity\": false
|
||||
}")
|
||||
|
||||
APP_ID=$(echo "$APP_RESPONSE" | jq -r '.result.id')
|
||||
fi
|
||||
|
||||
if [ ! -z "$APP_ID" ] && [ "$APP_ID" != "null" ]; then
|
||||
# Create/update policy
|
||||
POLICY_RESPONSE=$(curl -s -X POST "https://api.cloudflare.com/client/v4/zones/$CF_ZONE_ID/access/apps/$APP_ID/policies" \
|
||||
-H "Authorization: Bearer $CF_API_TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
--data "{
|
||||
\"name\": \"Email Policy\",
|
||||
\"decision\": \"allow\",
|
||||
\"include\": [{
|
||||
\"email\": {\"email\": \"$ADMIN_EMAIL\"}
|
||||
}]
|
||||
}")
|
||||
|
||||
if echo "$POLICY_RESPONSE" | jq -e '.success' > /dev/null; then
|
||||
echo " ✅ Access policy configured"
|
||||
else
|
||||
echo " ⚠️ Policy may already exist or update failed"
|
||||
fi
|
||||
else
|
||||
echo " ❌ Failed to create access application"
|
||||
fi
|
||||
done
|
||||
else
|
||||
echo "Invalid email format. Skipping access policy setup."
|
||||
echo "You can configure access policies manually in the Cloudflare dashboard."
|
||||
fi
|
||||
}
|
||||
|
||||
# Check if services are running
|
||||
check_services() {
|
||||
echo "Checking if services are running..."
|
||||
|
||||
local all_running=true
|
||||
|
||||
# Check common ports to see if services are running
|
||||
if ! nc -z localhost ${HOMEPAGE_PORT:-3010} >/dev/null 2>&1; then
|
||||
echo "❌ Homepage service not detected on port ${HOMEPAGE_PORT:-3010}"
|
||||
all_running=false
|
||||
fi
|
||||
|
||||
if ! nc -z localhost ${CODE_SERVER_PORT:-8888} >/dev/null 2>&1; then
|
||||
echo "❌ Code Server service not detected on port ${CODE_SERVER_PORT:-8888}"
|
||||
all_running=false
|
||||
fi
|
||||
|
||||
if ! nc -z localhost ${LISTMONK_PORT:-9000} >/dev/null 2>&1; then
|
||||
echo "❌ Listmonk service not detected on port ${LISTMONK_PORT:-9000}"
|
||||
all_running=false
|
||||
fi
|
||||
|
||||
# At least check that some services are running
|
||||
if [ "$all_running" = false ]; then
|
||||
echo "Warning: Some services may not be running."
|
||||
read -p "Continue anyway? (y/n): " continue_answer
|
||||
if [[ ! "$continue_answer" =~ ^[Yy]$ ]]; then
|
||||
echo "Please start your services with 'docker compose up -d' first."
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
else
|
||||
echo "Invalid email format. Skipping access policy setup."
|
||||
else
|
||||
echo "✅ Services appear to be running"
|
||||
fi
|
||||
}
|
||||
|
||||
# Add this function to verify Cloudflare API credentials
|
||||
verify_cloudflare_credentials() {
|
||||
echo "Verifying Cloudflare API credentials..."
|
||||
|
||||
# Test the API token and Zone ID with a simple request
|
||||
local TEST_RESPONSE=$(curl -s -X GET "https://api.cloudflare.com/client/v4/zones/$CF_ZONE_ID" \
|
||||
-H "Authorization: Bearer $CF_API_TOKEN" \
|
||||
-H "Content-Type: application/json")
|
||||
|
||||
if echo "$TEST_RESPONSE" | jq -e '.success' > /dev/null 2>&1; then
|
||||
echo "✅ Cloudflare API credentials verified successfully"
|
||||
return 0
|
||||
else
|
||||
echo "❌ Cloudflare API credentials verification failed"
|
||||
echo "Error details:"
|
||||
echo "$TEST_RESPONSE" | jq '.errors'
|
||||
echo ""
|
||||
echo "Common issues:"
|
||||
echo "1. Zone ID may be incorrect - make sure you're using the correct Zone ID from the Cloudflare dashboard"
|
||||
echo "2. API Token may not have the required permissions - make sure it has Zone:DNS and Zone:Settings permissions"
|
||||
echo ""
|
||||
echo "Your current Zone ID: $CF_ZONE_ID"
|
||||
echo "To continue without configuring DNS records, enter 'continue'. To quit and fix the credentials, enter 'quit'."
|
||||
read -p "Continue or quit? [continue/quit]: " cf_choice
|
||||
|
||||
if [[ "$cf_choice" == "quit" ]]; then
|
||||
echo "Exiting. Please update your credentials in .env and try again."
|
||||
exit 1
|
||||
else
|
||||
echo "Continuing without configuring DNS records..."
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
# Main execution flow
|
||||
echo "Starting Changemaker.lite production deployment..."
|
||||
|
||||
# Check if services are running
|
||||
check_services
|
||||
|
||||
# Check if cloudflared is installed, install if needed
|
||||
check_cloudflared
|
||||
|
||||
# Authenticate with Cloudflare
|
||||
authenticate_cloudflare
|
||||
|
||||
# Set up tunnel
|
||||
setup_tunnel
|
||||
|
||||
# Create systemd service
|
||||
create_systemd_service
|
||||
|
||||
# Verify Cloudflare credentials before proceeding with DNS configuration
|
||||
CF_CREDS_VALID=true
|
||||
if ! verify_cloudflare_credentials; then
|
||||
CF_CREDS_VALID=false
|
||||
echo "Skipping DNS record creation and access policy setup due to invalid credentials"
|
||||
fi
|
||||
|
||||
# Enable cloudflared in docker-compose
|
||||
echo ""
|
||||
echo "Enabling cloudflared container..."
|
||||
# Only proceed with DNS configuration if credentials are valid
|
||||
if [ "$CF_CREDS_VALID" = true ]; then
|
||||
# Create/update DNS records
|
||||
echo ""
|
||||
echo "Creating/updating DNS records..."
|
||||
|
||||
# Uncomment cloudflared service in docker-compose.yml
|
||||
sed -i '/# cloudflared:/,/# gitea-app/s/^ # / /' "$DOCKER_COMPOSE_FILE"
|
||||
# Define subdomains
|
||||
declare -A SUBDOMAINS=(
|
||||
["homepage"]="Homepage"
|
||||
["code"]="Code Server"
|
||||
["listmonk"]="Listmonk"
|
||||
["docs"]="Documentation"
|
||||
["n8n"]="n8n"
|
||||
["db"]="NocoDB"
|
||||
["git"]="Gitea"
|
||||
["map"]="Map"
|
||||
["qr"]="Mini QR"
|
||||
)
|
||||
|
||||
# Start cloudflared container
|
||||
docker compose up -d cloudflared
|
||||
for subdomain in "${!SUBDOMAINS[@]}"; do
|
||||
create_dns_record "$subdomain"
|
||||
done
|
||||
|
||||
# Create root domain record
|
||||
create_dns_record "@"
|
||||
|
||||
echo ""
|
||||
echo "✅ All DNS records configured"
|
||||
|
||||
# Set up access policies
|
||||
setup_access_policies
|
||||
else
|
||||
echo ""
|
||||
echo "⚠️ DNS records and access policies were not configured."
|
||||
echo "To manually configure DNS records, you can use the Cloudflare dashboard."
|
||||
echo "Add CNAME records for each subdomain pointing to: $CF_TUNNEL_ID.cfargotunnel.com"
|
||||
echo ""
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "#############################################################"
|
||||
echo "# "
|
||||
echo "# Production Setup Complete! "
|
||||
echo "# Production Deployment Complete! "
|
||||
echo "# "
|
||||
echo "#############################################################"
|
||||
echo ""
|
||||
@ -328,21 +606,13 @@ echo " - Documentation: https://docs.$CF_DOMAIN"
|
||||
echo " - n8n: https://n8n.$CF_DOMAIN"
|
||||
echo " - NocoDB: https://db.$CF_DOMAIN"
|
||||
echo " - Gitea: https://git.$CF_DOMAIN"
|
||||
echo " - Map: https://map.$CF_DOMAIN"
|
||||
echo " - Mini QR: https://qr.$CF_DOMAIN"
|
||||
echo ""
|
||||
if [ ! -z "$ADMIN_EMAIL" ]; then
|
||||
echo "Protected services (login required with $ADMIN_EMAIL):"
|
||||
echo " - Dashboard: https://dashboard.$CF_DOMAIN"
|
||||
echo " - Code Server: https://code.$CF_DOMAIN"
|
||||
else
|
||||
echo "Admin services (no protection configured):"
|
||||
echo " - Dashboard: https://dashboard.$CF_DOMAIN"
|
||||
echo " - Code Server: https://code.$CF_DOMAIN"
|
||||
fi
|
||||
echo "Protected services (requires login with $ADMIN_EMAIL):"
|
||||
echo " - Dashboard: https://homepage.$CF_DOMAIN"
|
||||
echo " - Code Server: https://code.$CF_DOMAIN"
|
||||
echo ""
|
||||
echo "Note: DNS propagation may take a few minutes."
|
||||
echo "Cloudflared service status: sudo systemctl status $SERVICE_NAME"
|
||||
echo "View tunnel logs: sudo journalctl -u $SERVICE_NAME -f"
|
||||
echo ""
|
||||
echo "To stop production mode and return to local-only:"
|
||||
echo " docker compose stop cloudflared"
|
||||
echo ""
|
||||
echo "To fully remove production setup:"
|
||||
echo " docker compose down cloudflared"
|
||||
Loading…
x
Reference in New Issue
Block a user