From 2f7d77b3c38520208a4e578ffa220b230c3f10f1 Mon Sep 17 00:00:00 2001 From: Charles N Wyble Date: Mon, 21 Apr 2025 14:12:15 -0400 Subject: [PATCH] . --- .../CloudronManifest.json | 53 +++++++++ .../rundeck.knownelement.com/jaas-ldap.conf | 22 ++++ Techops/rundeck.knownelement.com/nginx.conf | 34 ++++++ Techops/rundeck.knownelement.com/start.sh | 104 ++++++++++++++++++ .../rundeck.knownelement.com/supervisord.conf | 29 +++++ 5 files changed, 242 insertions(+) create mode 100644 Techops/rundeck.knownelement.com/CloudronManifest.json create mode 100644 Techops/rundeck.knownelement.com/jaas-ldap.conf create mode 100644 Techops/rundeck.knownelement.com/nginx.conf create mode 100644 Techops/rundeck.knownelement.com/start.sh create mode 100644 Techops/rundeck.knownelement.com/supervisord.conf diff --git a/Techops/rundeck.knownelement.com/CloudronManifest.json b/Techops/rundeck.knownelement.com/CloudronManifest.json new file mode 100644 index 0000000..f96875a --- /dev/null +++ b/Techops/rundeck.knownelement.com/CloudronManifest.json @@ -0,0 +1,53 @@ +{ + "id": "com.rundeck.cloudron", + "title": "Rundeck", + "author": "Rundeck, Inc.", + "description": "Job scheduler and runbook automation for teams. Rundeck enables self-service operations with policy-based access control, audit trail, and integrations with your existing tools.", + "tagline": "Job scheduling and runbook automation", + "version": "1.0.0", + "healthCheckPath": "/api/40/system/info", + "httpPort": 8080, + "manifestVersion": 2, + "website": "https://www.rundeck.com/", + "contactEmail": "support@rundeck.com", + "icon": "file://logo.png", + "addons": { + "localstorage": {}, + "postgresql": { + "version": "14" + } + }, + "tags": [ + "automation", + "devops", + "scheduler", + "workflow" + ], + "minBoxVersion": "7.4.0", + "memoryLimit": 1024, + "documentationUrl": "https://docs.rundeck.com/", + "postInstallMessage": "Rundeck has been installed. The initial admin credentials are:\nUsername: admin\nPassword: {{ .password }}\n\nPlease change this password immediately after login.", + "startCommand": "/app/code/start.sh", + "configurePath": "/login", + "mediaLinks": [], + "changelog": [ + { + "versionCode": 1, + "version": "1.0.0", + "releaseDate": "2025-04-21", + "changes": [ + "Initial release of Rundeck for Cloudron" + ] + } + ], + "forumUrl": "https://github.com/cloudron-io/cloudron-app/issues", + "features": { + "ldap": true, + "oauth": { + "callback": "/user/oidclogin", + "clientId": "{{ cloudron.oauth.clientId }}", + "clientSecret": "{{ cloudron.oauth.clientSecret }}", + "scope": "profile email" + } + } +} \ No newline at end of file diff --git a/Techops/rundeck.knownelement.com/jaas-ldap.conf b/Techops/rundeck.knownelement.com/jaas-ldap.conf new file mode 100644 index 0000000..5a82f5e --- /dev/null +++ b/Techops/rundeck.knownelement.com/jaas-ldap.conf @@ -0,0 +1,22 @@ +ldap { + com.dtolabs.rundeck.jetty.jaas.JettyCachingLdapLoginModule required + debug="true" + contextFactory="com.sun.jndi.ldap.LdapCtxFactory" + providerUrl="{{ldap.url}}" + bindDn="{{ldap.bindDn}}" + bindPassword="{{ldap.bindPassword}}" + authenticationMethod="simple" + forceBindingLogin="true" + userBaseDn="{{ldap.userBaseDn}}" + userRdnAttribute="uid" + userIdAttribute="uid" + userPasswordAttribute="userPassword" + userObjectClass="inetOrgPerson" + roleBaseDn="{{ldap.groupBaseDn}}" + roleNameAttribute="cn" + roleMemberAttribute="member" + roleObjectClass="groupOfNames" + cacheDurationMillis="300000" + supplementalRoles="user" + reportStatistics="true"; +}; \ No newline at end of file diff --git a/Techops/rundeck.knownelement.com/nginx.conf b/Techops/rundeck.knownelement.com/nginx.conf new file mode 100644 index 0000000..11ef1cf --- /dev/null +++ b/Techops/rundeck.knownelement.com/nginx.conf @@ -0,0 +1,34 @@ +server { + listen 8080; + server_name localhost; + + access_log /dev/stdout; + error_log /dev/stderr; + + client_max_body_size 50M; + + location / { + proxy_pass http://127.0.0.1:4440; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header X-Forwarded-Host $host; + proxy_set_header X-Forwarded-Server $host; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + proxy_read_timeout 86400; + } + + # OIDC callback + location /user/oidclogin { + proxy_pass http://127.0.0.1:4440/user/oidclogin; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header X-Forwarded-Host $host; + proxy_set_header X-Forwarded-Server $host; + } +} \ No newline at end of file diff --git a/Techops/rundeck.knownelement.com/start.sh b/Techops/rundeck.knownelement.com/start.sh new file mode 100644 index 0000000..1fecdf0 --- /dev/null +++ b/Techops/rundeck.knownelement.com/start.sh @@ -0,0 +1,104 @@ +#!/bin/bash + +set -eu + +# Setup runtime environment +echo "Setting up Rundeck runtime environment..." + +# Initialize data directories if they don't exist +for dir in etc server/data var/logs projects libext .ssh; do + if [ ! -d "/app/data/$dir" ]; then + mkdir -p "/app/data/$dir" + if [ -d "/tmp/data/$dir" ] && [ -n "$(ls -A "/tmp/data/$dir" 2>/dev/null)" ]; then + cp -r "/tmp/data/$dir/"* "/app/data/$dir/" + fi + fi +done + +# Setup database connection +DB_URL="jdbc:postgresql://${CLOUDRON_POSTGRESQL_HOST}:${CLOUDRON_POSTGRESQL_PORT}/${CLOUDRON_POSTGRESQL_DATABASE}?user=${CLOUDRON_POSTGRESQL_USERNAME}&password=${CLOUDRON_POSTGRESQL_PASSWORD}" +export RUNDECK_SERVER_DATASTORE_URL="$DB_URL" +export RUNDECK_DATABASE_URL="$DB_URL" +export RUNDECK_DATABASE_DRIVER="org.postgresql.Driver" +export RUNDECK_DATABASE_USERNAME="${CLOUDRON_POSTGRESQL_USERNAME}" +export RUNDECK_DATABASE_PASSWORD="${CLOUDRON_POSTGRESQL_PASSWORD}" + +# Generate initial admin password if not exists +if ! grep -q "^admin:" /app/data/etc/realm.properties 2>/dev/null; then + PASSWORD=$(openssl rand -hex 8) + echo "admin:admin,user,admin" > /app/data/etc/realm.properties + sed -i "s|{{ .password }}|$PASSWORD|g" /run/cloudron/app.json +else + sed -i "s|{{ .password }}||g" /run/cloudron/app.json +fi + +# Update configurations +if [ -f "/app/data/etc/framework.properties" ]; then + # Set domain in framework.properties + sed -i "s|framework.server.url = .*|framework.server.url = https://${CLOUDRON_APP_DOMAIN}|g" /app/data/etc/framework.properties + sed -i "s|framework.server.hostname = .*|framework.server.hostname = ${CLOUDRON_APP_DOMAIN}|g" /app/data/etc/framework.properties +fi + +if [ -f "/app/data/etc/rundeck-config.properties" ]; then + # Update database connection in rundeck-config.properties + sed -i "s|dataSource.url = .*|dataSource.url = ${RUNDECK_SERVER_DATASTORE_URL}|g" /app/data/etc/rundeck-config.properties + sed -i "s|grails.serverURL = .*|grails.serverURL = https://${CLOUDRON_APP_DOMAIN}|g" /app/data/etc/rundeck-config.properties +fi + +# Configure authentication +if [[ -n "${CLOUDRON_OAUTH_IDENTIFIER:-}" ]]; then + echo "Configuring OAuth/OIDC authentication..." + export RUNDECK_SECURITY_OAUTH_ENABLED=true + export RUNDECK_SECURITY_OAUTH_CLIENTID="${CLOUDRON_OAUTH_CLIENT_ID}" + export RUNDECK_SECURITY_OAUTH_CLIENTSECRET="${CLOUDRON_OAUTH_CLIENT_SECRET}" + export RUNDECK_SECURITY_OAUTH_AUTHORIZEURL="${CLOUDRON_OAUTH_ORIGIN}/auth/realms/${CLOUDRON_OAUTH_IDENTIFIER}/protocol/openid-connect/auth" + export RUNDECK_SECURITY_OAUTH_TOKENURL="${CLOUDRON_OAUTH_ORIGIN}/auth/realms/${CLOUDRON_OAUTH_IDENTIFIER}/protocol/openid-connect/token" + export RUNDECK_SECURITY_OAUTH_USERINFOURI="${CLOUDRON_OAUTH_ORIGIN}/auth/realms/${CLOUDRON_OAUTH_IDENTIFIER}/protocol/openid-connect/userinfo" + + cp /tmp/data/etc/jaas-oidc.conf /app/data/etc/jaas-oidc.conf + export RUNDECK_JAASLOGIN=true + export RDECK_JVM_OPTS="${RDECK_JVM_OPTS:-} -Drundeck.jaaslogin=true -Dloginmodule.name=oauth -Djava.security.auth.login.config=/app/data/etc/jaas-oidc.conf" + + # Add necessary properties to rundeck-config.properties + echo "rundeck.security.oauth.enabled=true" >> /app/data/etc/rundeck-config.properties + echo "rundeck.security.oauth.clientId=${CLOUDRON_OAUTH_CLIENT_ID}" >> /app/data/etc/rundeck-config.properties + echo "rundeck.security.oauth.clientSecret=${CLOUDRON_OAUTH_CLIENT_SECRET}" >> /app/data/etc/rundeck-config.properties + echo "rundeck.security.oauth.authorizeUrl=${CLOUDRON_OAUTH_ORIGIN}/auth/realms/${CLOUDRON_OAUTH_IDENTIFIER}/protocol/openid-connect/auth" >> /app/data/etc/rundeck-config.properties + echo "rundeck.security.oauth.tokenUrl=${CLOUDRON_OAUTH_ORIGIN}/auth/realms/${CLOUDRON_OAUTH_IDENTIFIER}/protocol/openid-connect/token" >> /app/data/etc/rundeck-config.properties + echo "rundeck.security.oauth.userInfoUri=${CLOUDRON_OAUTH_ORIGIN}/auth/realms/${CLOUDRON_OAUTH_IDENTIFIER}/protocol/openid-connect/userinfo" >> /app/data/etc/rundeck-config.properties + echo "rundeck.security.oauth.autoCreateUsers=true" >> /app/data/etc/rundeck-config.properties + echo "rundeck.security.oauth.defaultRoles=user" >> /app/data/etc/rundeck-config.properties +elif [[ -n "${CLOUDRON_LDAP_SERVER:-}" ]]; then + echo "Configuring LDAP authentication..." + cp /tmp/data/etc/jaas-ldap.conf /app/data/etc/jaas-ldap.conf + + # Replace placeholders in JAAS config + sed -i "s|{{ldap.url}}|${CLOUDRON_LDAP_SERVER}:${CLOUDRON_LDAP_PORT}|g" /app/data/etc/jaas-ldap.conf + sed -i "s|{{ldap.bindDn}}|${CLOUDRON_LDAP_BIND_DN}|g" /app/data/etc/jaas-ldap.conf + sed -i "s|{{ldap.bindPassword}}|${CLOUDRON_LDAP_BIND_PASSWORD}|g" /app/data/etc/jaas-ldap.conf + sed -i "s|{{ldap.userBaseDn}}|${CLOUDRON_LDAP_USERS_BASE_DN}|g" /app/data/etc/jaas-ldap.conf + sed -i "s|{{ldap.groupBaseDn}}|${CLOUDRON_LDAP_GROUPS_BASE_DN}|g" /app/data/etc/jaas-ldap.conf + + export RUNDECK_JAASLOGIN=true + export RDECK_JVM_OPTS="${RDECK_JVM_OPTS:-} -Drundeck.jaaslogin=true -Dloginmodule.name=ldap -Djava.security.auth.login.config=/app/data/etc/jaas-ldap.conf" + + # Enable JAAS LDAP in rundeck-config.properties + echo "rundeck.security.jaasLoginModuleName=ldap" >> /app/data/etc/rundeck-config.properties + echo "rundeck.security.jaasProviderName=ldap" >> /app/data/etc/rundeck-config.properties + echo "rundeck.jaaslogin=true" >> /app/data/etc/rundeck-config.properties + echo "rundeck.feature.caseInsensitiveUsername.enabled=true" >> /app/data/etc/rundeck-config.properties + echo "rundeck.security.syncLdapUser=true" >> /app/data/etc/rundeck-config.properties +else + # Use file-based authentication + echo "Using file-based authentication..." + export RDECK_JVM_OPTS="${RDECK_JVM_OPTS:-} -Drundeck.jaaslogin=true -Dloginmodule.name=file -Djava.security.auth.login.config=/app/data/etc/jaas-file.conf" + echo 'RDpropertyfilelogin { org.eclipse.jetty.jaas.spi.PropertyFileLoginModule required debug="true" file="/app/data/etc/realm.properties"; };' > /app/data/etc/jaas-file.conf + echo "rundeck.security.jaasLoginModuleName=file" >> /app/data/etc/rundeck-config.properties + echo "rundeck.security.jaasProviderName=file" >> /app/data/etc/rundeck-config.properties +fi + +# Set permissions +chown -R cloudron:cloudron /app/data + +echo "Starting Rundeck services..." +exec /usr/bin/supervisord -c /etc/supervisor/conf.d/supervisord.conf \ No newline at end of file diff --git a/Techops/rundeck.knownelement.com/supervisord.conf b/Techops/rundeck.knownelement.com/supervisord.conf new file mode 100644 index 0000000..42529db --- /dev/null +++ b/Techops/rundeck.knownelement.com/supervisord.conf @@ -0,0 +1,29 @@ +[supervisord] +nodaemon=true +user=root +logfile=/dev/stdout +logfile_maxbytes=0 +pidfile=/var/run/supervisord.pid + +[program:rundeck] +command=java -Xmx512m -Dserver.http.port=4440 -Drdeck.base=/app/data -jar /app/code/rundeck/webapps/rundeck.war +directory=/app/code/rundeck +user=cloudron +environment=RDECK_BASE="/app/data",RUNDECK_SERVER_DATASTORE_URL="%(ENV_RUNDECK_SERVER_DATASTORE_URL)s",RUNDECK_SERVER_DATASTORE_DRIVER="%(ENV_RUNDECK_SERVER_DATASTORE_DRIVER)s",RUNDECK_GRAILS_URL="%(ENV_RUNDECK_GRAILS_URL)s",RUNDECK_SERVER_CONTEXTPATH="%(ENV_RUNDECK_SERVER_CONTEXTPATH)s",RUNDECK_SERVER_FORWARDED=%(ENV_RUNDECK_SERVER_FORWARDED)s,RUNDECK_LOGGING_STRATEGY="%(ENV_RUNDECK_LOGGING_STRATEGY)s",SERVER_SERVLET_CONTEXT_PATH="%(ENV_SERVER_SERVLET_CONTEXT_PATH)s",RUNDECK_JAASLOGIN=%(ENV_RUNDECK_JAASLOGIN)s,RUNDECK_SERVER_ADDRESS=%(ENV_RUNDECK_SERVER_ADDRESS)s,RUNDECK_SERVER_PORT=%(ENV_RUNDECK_SERVER_PORT)s +stdout_logfile=/dev/stdout +stdout_logfile_maxbytes=0 +stderr_logfile=/dev/stderr +stderr_logfile_maxbytes=0 +autorestart=true +priority=10 +startretries=5 +stopwaitsecs=60 + +[program:nginx] +command=/usr/sbin/nginx -g "daemon off;" +stdout_logfile=/dev/stdout +stdout_logfile_maxbytes=0 +stderr_logfile=/dev/stderr +stderr_logfile_maxbytes=0 +autorestart=true +priority=20 \ No newline at end of file