cleanup
This commit is contained in:
@@ -0,0 +1,30 @@
|
||||
{
|
||||
"id": "com.easygate.cloudron",
|
||||
"title": "Easy-gate",
|
||||
"author": "r7wx",
|
||||
"description": "A simple web application designed to serve as the central hub for your self-hosted infrastructure. Easy-gate provides real-time parsing of services and notes from a configuration file.",
|
||||
"tagline": "A gate to your self-hosted infrastructure",
|
||||
"version": "1.0.0",
|
||||
"healthCheckPath": "/",
|
||||
"httpPort": 8080,
|
||||
"addons": {
|
||||
"localstorage": {}
|
||||
},
|
||||
"manifestVersion": 2,
|
||||
"website": "https://github.com/r7wx/easy-gate",
|
||||
"contactEmail": "support@cloudron.io",
|
||||
"icon": "logo.png",
|
||||
"tags": [
|
||||
"dashboard",
|
||||
"infrastructure",
|
||||
"services",
|
||||
"homepage"
|
||||
],
|
||||
"env": {
|
||||
"EASY_GATE_CONFIG": "/app/data/easy-gate.json",
|
||||
"EASY_GATE_ROOT_PATH": "/app/data"
|
||||
},
|
||||
"configurePath": "/",
|
||||
"minBoxVersion": "7.0.0",
|
||||
"postInstallMessage": "Easy-gate has been successfully installed. You can now configure your services in the /app/data/easy-gate.json file. By default, Easy-gate runs behind Cloudron's proxy (EASY_GATE_BEHIND_PROXY=true). More configuration options available at https://github.com/r7wx/easy-gate"
|
||||
}
|
@@ -0,0 +1,41 @@
|
||||
FROM cloudron/base:4.2.0
|
||||
|
||||
# Adding non-free repo for any potential dependencies
|
||||
RUN apt-get update && \
|
||||
apt-get install -y --no-install-recommends \
|
||||
wget \
|
||||
ca-certificates \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Set up directory structure
|
||||
RUN mkdir -p /app/code /app/data /tmp/data
|
||||
|
||||
# Default config file
|
||||
COPY easy-gate.json /tmp/data/easy-gate.json
|
||||
|
||||
# Download and install the latest Easy-gate release
|
||||
RUN mkdir -p /tmp/easy-gate && \
|
||||
cd /tmp/easy-gate && \
|
||||
LATEST_VERSION=$(wget -qO- https://api.github.com/repos/r7wx/easy-gate/releases/latest | grep tag_name | cut -d '"' -f 4) && \
|
||||
wget -q https://github.com/r7wx/easy-gate/releases/download/${LATEST_VERSION}/easy-gate_${LATEST_VERSION#v}_linux_amd64.tar.gz && \
|
||||
tar -xzf easy-gate_${LATEST_VERSION#v}_linux_amd64.tar.gz && \
|
||||
mv easy-gate /app/code/ && \
|
||||
chmod +x /app/code/easy-gate && \
|
||||
rm -rf /tmp/easy-gate
|
||||
|
||||
# Prepare start script
|
||||
COPY start.sh /app/code/
|
||||
RUN chmod +x /app/code/start.sh
|
||||
|
||||
# Set proper permissions
|
||||
RUN chown -R cloudron:cloudron /app/code /app/data /tmp/data
|
||||
|
||||
# Configure working directory and user
|
||||
WORKDIR /app/code
|
||||
USER cloudron
|
||||
|
||||
# Expose the port the app runs on
|
||||
EXPOSE 8080
|
||||
|
||||
# Start the application
|
||||
CMD ["/app/code/start.sh"]
|
@@ -0,0 +1,147 @@
|
||||
# Easy-gate Build Notes for Cloudron
|
||||
|
||||
This document provides instructions for building, testing, and deploying Easy-gate to your Cloudron instance.
|
||||
|
||||
## Overview
|
||||
|
||||
Easy-gate is a simple web application designed to serve as the central hub for your self-hosted infrastructure. It allows you to organize and access all your self-hosted services from a single dashboard.
|
||||
|
||||
Key features:
|
||||
- Real-time parsing of services and notes from a configuration file (JSON/YAML)
|
||||
- Ability to assign items to specific user groups based on IP addresses
|
||||
- Organization of services into categories
|
||||
- Customizable theme and icons
|
||||
|
||||
## Building the Package
|
||||
|
||||
### Prerequisites
|
||||
|
||||
- A Linux environment with Docker installed
|
||||
- Cloudron CLI tool installed (`npm install -g cloudron`)
|
||||
- Authenticated with your Cloudron instance (`cloudron login`)
|
||||
|
||||
### Build Steps
|
||||
|
||||
1. Create a directory for your build and copy all files into it:
|
||||
|
||||
```bash
|
||||
mkdir easy-gate-build
|
||||
cd easy-gate-build
|
||||
# Copy CloudronManifest.json, Dockerfile, start.sh, and easy-gate.json
|
||||
```
|
||||
|
||||
2. Create a logo.png file for the icon or download one from the Easy-gate repository.
|
||||
|
||||
3. Build the package:
|
||||
|
||||
```bash
|
||||
cloudron build
|
||||
```
|
||||
|
||||
This command will create a package file (usually named `easy-gate-1.0.0.tar.gz`).
|
||||
|
||||
## Testing Locally
|
||||
|
||||
You can test the Docker container locally before deploying to Cloudron:
|
||||
|
||||
```bash
|
||||
# Build the Docker image
|
||||
docker build -t easy-gate-local .
|
||||
|
||||
# Run the container
|
||||
docker run -p 8080:8080 -e EASY_GATE_BEHIND_PROXY=true easy-gate-local
|
||||
```
|
||||
|
||||
Access the dashboard at http://localhost:8080 to verify it works correctly.
|
||||
|
||||
## Deploying to Cloudron
|
||||
|
||||
1. Upload the built package to your Cloudron:
|
||||
|
||||
```bash
|
||||
cloudron install —app easy-gate.example.com
|
||||
```
|
||||
|
||||
2. Or, if you want to update an existing installation:
|
||||
|
||||
```bash
|
||||
cloudron update —app easy-gate.example.com
|
||||
```
|
||||
|
||||
3. Configure your Easy-gate instance:
|
||||
|
||||
After installation, you’ll need to edit the configuration file to add your services. You can do this in two ways:
|
||||
|
||||
### Option 1: Using Cloudron File Manager
|
||||
|
||||
1. Go to your Cloudron dashboard
|
||||
2. Click on the Easy-gate application
|
||||
3. Go to “Files” tab
|
||||
4. Navigate to `/app/data/`
|
||||
5. Edit `easy-gate.json`
|
||||
|
||||
### Option 2: SSH Access
|
||||
|
||||
1. SSH into your Cloudron server
|
||||
2. Access the app’s data directory:
|
||||
```bash
|
||||
cloudron exec —app easy-gate.example.com
|
||||
```
|
||||
3. Edit the configuration file:
|
||||
```bash
|
||||
nano /app/data/easy-gate.json
|
||||
```
|
||||
|
||||
## Configuration File Structure
|
||||
|
||||
The configuration file uses the following structure:
|
||||
|
||||
```json
|
||||
{
|
||||
“title”: “My Dashboard”,
|
||||
“theme”: {
|
||||
“background”: “#f8f9fa”,
|
||||
“foreground”: “#212529”,
|
||||
“custom_css”: “”
|
||||
},
|
||||
“groups”: [
|
||||
{
|
||||
“name”: “group-name”,
|
||||
“subnet”: “192.168.1.1/24”
|
||||
}
|
||||
],
|
||||
“categories”: [
|
||||
{
|
||||
“name”: “Category Name”,
|
||||
“services”: [
|
||||
{
|
||||
“name”: “Service Name”,
|
||||
“url”: “https://service.example.com”,
|
||||
“description”: “Service Description”,
|
||||
“icon”: “”,
|
||||
“groups”: [“group-name”]
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
“notes”: [
|
||||
{
|
||||
“name”: “Note Title”,
|
||||
“text”: “Note Content”,
|
||||
“groups”: [“group-name”]
|
||||
}
|
||||
],
|
||||
“behind_proxy”: true
|
||||
}
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
- If you encounter “502 Bad Gateway” errors, check that the application is running inside the container: `cloudron logs -f —app easy-gate.example.com`
|
||||
- Make sure the `behind_proxy` setting is set to `true` in your configuration file
|
||||
- Verify that the user groups and subnets are configured correctly
|
||||
- Check the logs for any specific error messages
|
||||
|
||||
## Maintenance
|
||||
|
||||
Easy-gate is designed to be low-maintenance. To update to a newer version, simply rebuild the package with the latest release and update your Cloudron app.
|
@@ -0,0 +1,69 @@
|
||||
{
|
||||
"title": "My Self-Hosted Infrastructure",
|
||||
"theme": {
|
||||
"background": "#f8f9fa",
|
||||
"foreground": "#212529",
|
||||
"custom_css": ""
|
||||
},
|
||||
"groups": [
|
||||
{
|
||||
"name": "internal",
|
||||
"subnet": "192.168.1.1/24"
|
||||
},
|
||||
{
|
||||
"name": "admin",
|
||||
"subnet": "10.8.0.1/24"
|
||||
}
|
||||
],
|
||||
"categories": [
|
||||
{
|
||||
"name": "Applications",
|
||||
"services": [
|
||||
{
|
||||
"name": "Cloudron",
|
||||
"url": "https://my.example.com",
|
||||
"description": "My Cloudron Dashboard",
|
||||
"icon": "",
|
||||
"groups": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Media",
|
||||
"services": [
|
||||
{
|
||||
"name": "Jellyfin",
|
||||
"url": "https://jellyfin.example.com",
|
||||
"description": "Media Server",
|
||||
"icon": "",
|
||||
"groups": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Monitoring",
|
||||
"services": [
|
||||
{
|
||||
"name": "Grafana",
|
||||
"url": "https://grafana.example.com",
|
||||
"description": "Monitoring Dashboard",
|
||||
"icon": "",
|
||||
"groups": ["admin"]
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"notes": [
|
||||
{
|
||||
"name": "Welcome to Easy-gate",
|
||||
"text": "This is your new Easy-gate dashboard. Edit this configuration file to customize your services and notes.",
|
||||
"groups": []
|
||||
},
|
||||
{
|
||||
"name": "For Administrators",
|
||||
"text": "Admin-only information can be seen here when connecting from the admin subnet.",
|
||||
"groups": ["admin"]
|
||||
}
|
||||
],
|
||||
"behind_proxy": true
|
||||
}
|
20
Cloudron/WorkInProgress/dashboard.knownelement.com/start.sh
Normal file
20
Cloudron/WorkInProgress/dashboard.knownelement.com/start.sh
Normal file
@@ -0,0 +1,20 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
# Initialize data directory if it doesn't exist
|
||||
if [ ! -f /app/data/easy-gate.json ]; then
|
||||
echo "Initializing Easy-gate with default configuration..."
|
||||
cp /tmp/data/easy-gate.json /app/data/
|
||||
chown cloudron:cloudron /app/data/easy-gate.json
|
||||
fi
|
||||
|
||||
# Set environment variables
|
||||
export EASY_GATE_CONFIG="/app/data/easy-gate.json"
|
||||
export EASY_GATE_ROOT_PATH="/app/data"
|
||||
export EASY_GATE_BEHIND_PROXY="true"
|
||||
|
||||
echo "Starting Easy-gate with configuration at ${EASY_GATE_CONFIG}..."
|
||||
echo "Easy-gate is configured to run behind a proxy (EASY_GATE_BEHIND_PROXY=true)"
|
||||
|
||||
# Run the application
|
||||
exec /app/code/easy-gate
|
@@ -0,0 +1,30 @@
|
||||
{
|
||||
"id": "org.elabftw.cloudron",
|
||||
"title": "eLabFTW",
|
||||
"author": "Nicolas CARPi",
|
||||
"description": "Electronic laboratory notebook to track experiments, manage protocols, store laboratory inventory, communicate with others and more. Your best lab companion.",
|
||||
"tagline": "Electronic lab notebook for researchers",
|
||||
"version": "1.0.0",
|
||||
"healthCheckPath": "/",
|
||||
"httpPort": 8000,
|
||||
"addons": {
|
||||
"mysql": {},
|
||||
"localstorage": {}
|
||||
},
|
||||
"manifestVersion": 2,
|
||||
"website": "https://www.elabftw.net",
|
||||
"contactEmail": "support@example.com",
|
||||
"icon": "file://logo.png",
|
||||
"memoryLimit": 1024,
|
||||
"tags": ["science", "lab", "research", "notebook", "eln"],
|
||||
"minBoxVersion": "7.4.0",
|
||||
"postInstallMessage": "eLabFTW has been successfully installed! You will need to create a Sysadmin account when you first access the application.",
|
||||
"documentationUrl": "https://doc.elabftw.net/",
|
||||
"forwardedHeaders": ["X-Forwarded-For", "X-Forwarded-Proto", "X-Forwarded-Host"],
|
||||
"tcpPorts": {},
|
||||
"optionalSso": {
|
||||
"ldap": {
|
||||
"enabled": true
|
||||
}
|
||||
}
|
||||
}
|
59
Cloudron/WorkInProgress/elabftw.knownelement.com/Dockerfile
Normal file
59
Cloudron/WorkInProgress/elabftw.knownelement.com/Dockerfile
Normal file
@@ -0,0 +1,59 @@
|
||||
FROM cloudron/base:4.2.0
|
||||
|
||||
# Install required packages
|
||||
RUN apt-get update && \
|
||||
apt-get install -y \
|
||||
php-cli \
|
||||
php-fpm \
|
||||
php-mysql \
|
||||
php-curl \
|
||||
php-gd \
|
||||
php-intl \
|
||||
php-mbstring \
|
||||
php-xml \
|
||||
php-zip \
|
||||
php-bcmath \
|
||||
nginx \
|
||||
supervisor \
|
||||
curl \
|
||||
zip \
|
||||
unzip \
|
||||
git \
|
||||
&& apt-get clean && rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Install Composer
|
||||
RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
|
||||
|
||||
# Get the latest eLabFTW release
|
||||
WORKDIR /app/code
|
||||
RUN git clone https://github.com/elabftw/elabftw.git . && \
|
||||
composer install --no-dev --optimize-autoloader
|
||||
|
||||
# Configure NGINX
|
||||
COPY nginx.conf /etc/nginx/sites-available/default
|
||||
|
||||
# Prepare directory structure
|
||||
RUN mkdir -p /app/data/uploads /app/data/config /app/data/logs /run/php && \
|
||||
chown -R cloudron:cloudron /app/data /run/php
|
||||
|
||||
# Copy initialization data
|
||||
RUN mkdir -p /tmp/data/config /tmp/data/uploads /tmp/data/logs && \
|
||||
cp -r /app/code/config-example.yml /tmp/data/config/config.yml && \
|
||||
chown -R cloudron:cloudron /tmp/data
|
||||
|
||||
# Copy start script and supervisor config
|
||||
COPY start.sh /app/code/
|
||||
COPY supervisord.conf /etc/supervisor/conf.d/supervisord.conf
|
||||
RUN chmod +x /app/code/start.sh
|
||||
|
||||
# Configure PHP-FPM
|
||||
RUN sed -i 's/www-data/cloudron/g' /etc/php/*/fpm/pool.d/www.conf && \
|
||||
sed -i 's/listen = \/run\/php\/php[0-9]\.[0-9]-fpm.sock/listen = \/run\/php\/php-fpm.sock/g' /etc/php/*/fpm/pool.d/www.conf && \
|
||||
echo 'catch_workers_output = yes' >> /etc/php/*/fpm/pool.d/www.conf
|
||||
|
||||
# Create logo image
|
||||
RUN curl -o /app/code/logo.png https://raw.githubusercontent.com/elabftw/elabftw/master/src/ts/img/logo.png
|
||||
|
||||
WORKDIR /app/code
|
||||
|
||||
CMD ["/app/code/start.sh"]
|
@@ -0,0 +1,109 @@
|
||||
# eLabFTW Cloudron Package Build Notes
|
||||
|
||||
This document provides instructions for building, testing, and deploying the eLabFTW Cloudron package.
|
||||
|
||||
## Package Overview
|
||||
|
||||
This package deploys eLabFTW, an open-source electronic laboratory notebook (ELN) for researchers, on Cloudron. The package:
|
||||
|
||||
- Uses the MySQL addon for database storage
|
||||
- Uses the localstorage addon for file storage
|
||||
- Includes NGINX and PHP-FPM configuration
|
||||
- Supports optional LDAP authentication through Cloudron
|
||||
|
||||
## Building the Package
|
||||
|
||||
1. Create a new directory for your package:
|
||||
```bash
|
||||
mkdir elabftw-cloudron
|
||||
cd elabftw-cloudron
|
||||
```
|
||||
|
||||
2. Save all the provided files to this directory:
|
||||
- CloudronManifest.json
|
||||
- Dockerfile
|
||||
- start.sh
|
||||
- nginx.conf
|
||||
- supervisord.conf
|
||||
|
||||
3. Make the start.sh file executable:
|
||||
```bash
|
||||
chmod +x start.sh
|
||||
```
|
||||
|
||||
4. Download the eLabFTW logo for the package icon:
|
||||
```bash
|
||||
curl -o logo.png https://raw.githubusercontent.com/elabftw/elabftw/master/src/ts/img/logo.png
|
||||
```
|
||||
|
||||
5. Build the package:
|
||||
```bash
|
||||
cloudron build
|
||||
```
|
||||
|
||||
## Testing the Package
|
||||
|
||||
1. Install the package on your Cloudron for testing:
|
||||
```bash
|
||||
cloudron install —location elabftw.example.com
|
||||
```
|
||||
|
||||
2. After installation, visit the application URL and complete the initial setup:
|
||||
- Create the Sysadmin account
|
||||
- Configure your teams and user groups
|
||||
- Set up any initial templates or protocols
|
||||
|
||||
3. Test the following functionality:
|
||||
- User authentication (local accounts)
|
||||
- File uploads (should be stored in /app/data/uploads)
|
||||
- Database connection (should be using Cloudron MySQL)
|
||||
- LDAP authentication (if enabled)
|
||||
- General application functionality
|
||||
|
||||
## Deploying to Production
|
||||
|
||||
1. Once testing is complete, you can deploy to production:
|
||||
```bash
|
||||
cloudron install —location elabftw.yourdomain.com
|
||||
```
|
||||
|
||||
2. For production use, consider:
|
||||
- Setting up regular backups of the Cloudron app
|
||||
- Configuring LDAP authentication if needed (via Cloudron UI)
|
||||
- Adjusting memory limits in CloudronManifest.json if necessary based on usage
|
||||
|
||||
## Post-Installation
|
||||
|
||||
After installation, you’ll need to:
|
||||
|
||||
1. Create a Sysadmin account when first accessing the application
|
||||
2. Configure teams and user groups
|
||||
3. Set up experiment templates and protocols as needed
|
||||
4. Consider enabling and configuring LDAP authentication for easier user management
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
- Check logs with `cloudron logs -f elabftw`
|
||||
- If database issues occur, verify the MySQL addon is properly configured
|
||||
- For file storage issues, check permissions on /app/data directories
|
||||
- For authentication issues, verify LDAP configuration (if using LDAP)
|
||||
|
||||
## Updates
|
||||
|
||||
When a new version of eLabFTW is released:
|
||||
|
||||
1. Update the git clone command in the Dockerfile to point to the latest release (or specific tag)
|
||||
2. Rebuild and update your package:
|
||||
```bash
|
||||
cloudron build
|
||||
cloudron update —app elabftw.yourdomain.com
|
||||
```
|
||||
|
||||
## Customization
|
||||
|
||||
You can customize the package by:
|
||||
|
||||
1. Modifying the config.yml template in /tmp/data/config to set default values
|
||||
2. Adjusting PHP settings in the Dockerfile or php.ini
|
||||
3. Modifying NGINX configuration for special requirements
|
||||
4. Adjusting memory limits in CloudronManifest.json based on usage patterns
|
38
Cloudron/WorkInProgress/elabftw.knownelement.com/nginx.conf
Normal file
38
Cloudron/WorkInProgress/elabftw.knownelement.com/nginx.conf
Normal file
@@ -0,0 +1,38 @@
|
||||
server {
|
||||
listen 8000;
|
||||
server_name _;
|
||||
root /app/code/web;
|
||||
index index.php;
|
||||
|
||||
client_max_body_size 100M;
|
||||
|
||||
access_log /dev/stdout;
|
||||
error_log /dev/stderr;
|
||||
|
||||
location / {
|
||||
try_files $uri /index.php$is_args$args;
|
||||
}
|
||||
|
||||
location ~ ^/index\.php(/|$) {
|
||||
fastcgi_pass unix:/run/php/php-fpm.sock;
|
||||
fastcgi_split_path_info ^(.+\.php)(/.*)$;
|
||||
include fastcgi_params;
|
||||
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
||||
fastcgi_param HTTPS on;
|
||||
|
||||
# Forward Cloudron proxy headers
|
||||
fastcgi_param HTTP_X_FORWARDED_FOR $http_x_forwarded_for;
|
||||
fastcgi_param HTTP_X_FORWARDED_PROTO $http_x_forwarded_proto;
|
||||
fastcgi_param HTTP_X_FORWARDED_HOST $http_x_forwarded_host;
|
||||
}
|
||||
|
||||
# Deny access to other PHP files
|
||||
location ~ \.php$ {
|
||||
return 404;
|
||||
}
|
||||
|
||||
# Rewrite app routes
|
||||
location @rewriteapp {
|
||||
rewrite ^(.*)$ /index.php/$1 last;
|
||||
}
|
||||
}
|
53
Cloudron/WorkInProgress/elabftw.knownelement.com/start.sh
Normal file
53
Cloudron/WorkInProgress/elabftw.knownelement.com/start.sh
Normal file
@@ -0,0 +1,53 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
# Create directory structure if it doesn't exist
|
||||
if [ ! -d /app/data/uploads ]; then
|
||||
mkdir -p /app/data/uploads
|
||||
cp -r /tmp/data/uploads/* /app/data/uploads/ 2>/dev/null || true
|
||||
chown -R cloudron:cloudron /app/data/uploads
|
||||
fi
|
||||
|
||||
if [ ! -d /app/data/logs ]; then
|
||||
mkdir -p /app/data/logs
|
||||
cp -r /tmp/data/logs/* /app/data/logs/ 2>/dev/null || true
|
||||
chown -R cloudron:cloudron /app/data/logs
|
||||
fi
|
||||
|
||||
if [ ! -f /app/data/config/config.yml ]; then
|
||||
mkdir -p /app/data/config
|
||||
cp -r /tmp/data/config/* /app/data/config/ 2>/dev/null || true
|
||||
|
||||
# Configure database connection
|
||||
sed -i "s/host: .*/host: ${CLOUDRON_MYSQL_HOST}/" /app/data/config/config.yml
|
||||
sed -i "s/port: .*/port: ${CLOUDRON_MYSQL_PORT}/" /app/data/config/config.yml
|
||||
sed -i "s/database: .*/database: ${CLOUDRON_MYSQL_DATABASE}/" /app/data/config/config.yml
|
||||
sed -i "s/username: .*/username: ${CLOUDRON_MYSQL_USERNAME}/" /app/data/config/config.yml
|
||||
sed -i "s/password: .*/password: ${CLOUDRON_MYSQL_PASSWORD}/" /app/data/config/config.yml
|
||||
|
||||
# Configure paths
|
||||
sed -i "s|uploads: .*|uploads: /app/data/uploads|" /app/data/config/config.yml
|
||||
sed -i "s|logs: .*|logs: /app/data/logs|" /app/data/config/config.yml
|
||||
|
||||
# Configure LDAP if enabled
|
||||
if [ "${CLOUDRON_LDAP_ENABLED}" == "true" ]; then
|
||||
# Update LDAP settings in config
|
||||
sed -i "s/ldap_enabled: .*/ldap_enabled: true/" /app/data/config/config.yml
|
||||
sed -i "s/ldap_host: .*/ldap_host: ${CLOUDRON_LDAP_SERVER}/" /app/data/config/config.yml
|
||||
sed -i "s/ldap_port: .*/ldap_port: ${CLOUDRON_LDAP_PORT}/" /app/data/config/config.yml
|
||||
sed -i "s/ldap_username: .*/ldap_username: ${CLOUDRON_LDAP_BIND_DN}/" /app/data/config/config.yml
|
||||
sed -i "s/ldap_password: .*/ldap_password: ${CLOUDRON_LDAP_BIND_PASSWORD}/" /app/data/config/config.yml
|
||||
sed -i "s/ldap_base_dn: .*/ldap_base_dn: ${CLOUDRON_LDAP_USERS_BASE_DN}/" /app/data/config/config.yml
|
||||
fi
|
||||
|
||||
chown -R cloudron:cloudron /app/data/config
|
||||
fi
|
||||
|
||||
# Create a symlink to the config file
|
||||
ln -sf /app/data/config/config.yml /app/code/config.yml
|
||||
|
||||
# Set proper permissions
|
||||
chown -R cloudron:cloudron /app/data
|
||||
|
||||
# Start the supervisord
|
||||
exec /usr/bin/supervisord -c /etc/supervisor/conf.d/supervisord.conf
|
@@ -0,0 +1,24 @@
|
||||
[supervisord]
|
||||
nodaemon=true
|
||||
logfile=/dev/stdout
|
||||
logfile_maxbytes=0
|
||||
|
||||
[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
|
||||
autostart=true
|
||||
autorestart=true
|
||||
priority=10
|
||||
|
||||
[program:php-fpm]
|
||||
command=/usr/sbin/php-fpm8.1 -F
|
||||
stdout_logfile=/dev/stdout
|
||||
stdout_logfile_maxbytes=0
|
||||
stderr_logfile=/dev/stderr
|
||||
stderr_logfile_maxbytes=0
|
||||
autostart=true
|
||||
autorestart=true
|
||||
priority=5
|
@@ -0,0 +1,44 @@
|
||||
{
|
||||
"id": "net.consuldemocracy.cloudron",
|
||||
"title": "Consul Democracy",
|
||||
"author": "Consul Democracy Community",
|
||||
"description": "Open Government and E-Participation Web Software",
|
||||
"tagline": "The most comprehensive citizen participation platform",
|
||||
"version": "1.0.0",
|
||||
"healthCheckPath": "/",
|
||||
"httpPort": 8000,
|
||||
"addons": {
|
||||
"localstorage": {},
|
||||
"postgresql": {
|
||||
"version": "14"
|
||||
},
|
||||
"ldap": {},
|
||||
"sendmail": {}
|
||||
},
|
||||
"manifestVersion": 2,
|
||||
"website": "https://consuldemocracy.org",
|
||||
"contactEmail": "info@consuldemocracy.org",
|
||||
"icon": "file://logo.png",
|
||||
"tags": [
|
||||
"democracy",
|
||||
"participation",
|
||||
"open-government",
|
||||
"rails"
|
||||
],
|
||||
"dockerImage": "{origin}/consuldemocracy",
|
||||
"memoryLimit": 1024,
|
||||
"documentationUrl": "https://docs.consuldemocracy.org/",
|
||||
"forumUrl": "https://github.com/consuldemocracy/consuldemocracy/discussions",
|
||||
"minBoxVersion": "7.0.0",
|
||||
"mediaLinks": [],
|
||||
"changelog": "Initial version",
|
||||
"postInstallMessage": "Consul Democracy has been successfully installed! The default administrator credentials are:\n\nUsername: admin@example.org\nPassword: password\n\nPlease login and change these immediately.",
|
||||
"configurePath": "/admin",
|
||||
"backup": {
|
||||
"backupScriptPath": "/app/code/backup.sh"
|
||||
},
|
||||
"sso": {
|
||||
"loginPath": "/users/sign_in",
|
||||
"callbackPath": "/oauth/callback"
|
||||
}
|
||||
}
|
@@ -0,0 +1,114 @@
|
||||
# Consul Democracy - Cloudron Build Notes
|
||||
|
||||
## Overview
|
||||
|
||||
Consul Democracy is an open-source citizen participation and open government platform, originally developed for the Madrid City government. This package enables easy deployment on the Cloudron platform with full integration of Cloudron’s authentication, database, and email systems.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- A running Cloudron instance (version 7.0.0 or later)
|
||||
- Basic familiarity with Cloudron’s CLI for package development
|
||||
- Git installed on your local machine
|
||||
|
||||
## Building the Package
|
||||
|
||||
1. Clone this repository:
|
||||
```bash
|
||||
git clone https://github.com/your-username/cloudron-consuldemocracy.git
|
||||
cd cloudron-consuldemocracy
|
||||
```
|
||||
|
||||
2. Install the Cloudron CLI if you haven’t already:
|
||||
```bash
|
||||
npm install -g cloudron
|
||||
```
|
||||
|
||||
3. Login to your Cloudron:
|
||||
```bash
|
||||
cloudron login https://my.example.com
|
||||
```
|
||||
|
||||
4. Build and install the package:
|
||||
```bash
|
||||
cloudron build
|
||||
cloudron install —image consuldemocracy
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
### Post-Installation
|
||||
|
||||
After installation, the app will be available at your configured domain. The initial admin credentials are:
|
||||
|
||||
- Username: admin@example.org
|
||||
- Password: password
|
||||
|
||||
**Important:** Change these credentials immediately after logging in.
|
||||
|
||||
### LDAP Integration
|
||||
|
||||
The package is configured to use Cloudron’s LDAP server for authentication. Users who have access to the app through Cloudron’s access control panel will be able to log in using their Cloudron credentials.
|
||||
|
||||
### OIDC Integration
|
||||
|
||||
For enhanced security, the package also supports Cloudron’s OIDC provider. This is automatically configured during installation.
|
||||
|
||||
### Email Configuration
|
||||
|
||||
The package is configured to use Cloudron’s SMTP server for sending emails. No additional configuration is needed.
|
||||
|
||||
## Customization
|
||||
|
||||
### Environment Variables
|
||||
|
||||
You can customize the app by setting environment variables in the Cloudron app configuration:
|
||||
|
||||
- `CONSUL_CUSTOM_LOGO`: URL to a custom logo
|
||||
- `CONSUL_ORGANIZATION_NAME`: Name of your organization
|
||||
- `CONSUL_THEME_COLOR`: Primary theme color (hex code)
|
||||
|
||||
### Filesystem Structure
|
||||
|
||||
- `/app/data/files`: Persistent storage for uploaded files
|
||||
- `/app/data/images`: Persistent storage for uploaded images
|
||||
- `/app/data/log`: Application logs
|
||||
- `/app/data/tmp`: Temporary files
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Common Issues
|
||||
|
||||
1. **Database Migration Errors**:
|
||||
Check the app logs for specific error messages:
|
||||
```bash
|
||||
cloudron logs -f
|
||||
```
|
||||
|
||||
2. **Authentication Issues**:
|
||||
Ensure that the LDAP configuration is correct and that users have been granted access to the app in Cloudron’s access control panel.
|
||||
|
||||
3. **Email Delivery Problems**:
|
||||
Verify that the Cloudron mail addon is properly configured.
|
||||
|
||||
### Support
|
||||
|
||||
For issues specific to this package:
|
||||
- Create an issue in the GitHub repository
|
||||
- Contact the maintainer at: your-email@example.com
|
||||
|
||||
For issues with Consul Democracy itself:
|
||||
- Visit the [Consul Democracy documentation](https://docs.consuldemocracy.org/)
|
||||
- Check the [GitHub issues](https://github.com/consuldemocracy/consuldemocracy/issues)
|
||||
|
||||
## Updates and Maintenance
|
||||
|
||||
To update the app:
|
||||
|
||||
1. Pull the latest changes from the repository
|
||||
2. Rebuild the package:
|
||||
```bash
|
||||
cloudron build
|
||||
cloudron update —app consuldemocracy
|
||||
```
|
||||
|
||||
Regular database backups are automatically handled by Cloudron’s backup system.
|
@@ -0,0 +1,93 @@
|
||||
FROM cloudron/base:4.2.0
|
||||
|
||||
# Install dependencies
|
||||
RUN apt-get update && apt-get install -y \
|
||||
build-essential \
|
||||
cmake \
|
||||
pkg-config \
|
||||
git \
|
||||
curl \
|
||||
ruby-full \
|
||||
nodejs \
|
||||
npm \
|
||||
imagemagick \
|
||||
libpq-dev \
|
||||
libxml2-dev \
|
||||
libxslt1-dev \
|
||||
zlib1g-dev \
|
||||
libyaml-dev \
|
||||
libssl-dev \
|
||||
libreadline-dev \
|
||||
supervisor \
|
||||
nginx \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Update npm and install yarn
|
||||
RUN npm install -g yarn
|
||||
|
||||
# Set Ruby and NodeJS versions
|
||||
ENV RUBY_VERSION=3.2.8
|
||||
ENV NODE_VERSION=18.20.3
|
||||
|
||||
# Ensure correct nodejs version (Node.js is already installed in base image)
|
||||
RUN n ${NODE_VERSION}
|
||||
|
||||
# Create app directory structure
|
||||
RUN mkdir -p /app/code /app/data /tmp/data
|
||||
|
||||
# Clone the app
|
||||
RUN git clone https://github.com/consuldemocracy/consuldemocracy.git /app/code
|
||||
WORKDIR /app/code
|
||||
|
||||
# Install bundler
|
||||
RUN gem install bundler
|
||||
|
||||
# Install gems
|
||||
RUN bundle install --deployment --without development test
|
||||
|
||||
# Install JavaScript dependencies
|
||||
RUN yarn install
|
||||
|
||||
# Precompile assets
|
||||
RUN SECRET_KEY_BASE=precompilation_key RAILS_ENV=production bundle exec rake assets:precompile
|
||||
|
||||
# Configure Nginx
|
||||
RUN rm -f /etc/nginx/sites-enabled/default
|
||||
COPY nginx.conf /etc/nginx/sites-enabled/consuldemocracy.conf
|
||||
|
||||
# Configure Supervisor
|
||||
COPY supervisord.conf /etc/supervisor/conf.d/consuldemocracy.conf
|
||||
|
||||
# Add initialization script for /app/data
|
||||
COPY init-data.sh /app/code/
|
||||
RUN chmod +x /app/code/init-data.sh
|
||||
|
||||
# Copy backup script
|
||||
COPY backup.sh /app/code/
|
||||
RUN chmod +x /app/code/backup.sh
|
||||
|
||||
# Copy database configuration
|
||||
COPY database.yml /app/code/config/database.yml
|
||||
|
||||
# Copy secrets configuration template
|
||||
COPY secrets.yml /app/code/config/secrets.yml
|
||||
|
||||
# Add LDAP configuration
|
||||
COPY ldap.yml /app/code/config/ldap.yml
|
||||
|
||||
# Copy oauth integration config
|
||||
COPY oauth.rb /app/code/config/initializers/oauth.rb
|
||||
|
||||
# Copy the startup script
|
||||
COPY start.sh /app/code/
|
||||
RUN chmod +x /app/code/start.sh
|
||||
|
||||
# Set appropriate permissions
|
||||
RUN chown -R cloudron:cloudron /app/code
|
||||
|
||||
# Configure app for production
|
||||
ENV RAILS_ENV=production
|
||||
ENV RAILS_SERVE_STATIC_FILES=true
|
||||
|
||||
# Entrypoint
|
||||
CMD ["/app/code/start.sh"]
|
@@ -0,0 +1,23 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
echo "Performing Consul Democracy backup..."
|
||||
|
||||
# The Cloudron backup system will automatically handle:
|
||||
# 1. /app/data
|
||||
# 2. PostgreSQL database
|
||||
|
||||
# We don't need any custom backup logic as Cloudron handles
|
||||
# both the database and the data directory.
|
||||
|
||||
# In case of any application-specific backup needs:
|
||||
|
||||
# 1. Run any pre-backup tasks
|
||||
cd /app/code
|
||||
RAILS_ENV=production bundle exec rake tmp:clear
|
||||
|
||||
# 2. Ensure all user uploads are synced
|
||||
sync
|
||||
|
||||
echo "Backup preparation complete"
|
||||
exit 0
|
@@ -0,0 +1,18 @@
|
||||
default: &default
|
||||
adapter: postgresql
|
||||
encoding: unicode
|
||||
pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
|
||||
timeout: 5000
|
||||
|
||||
development:
|
||||
<<: *default
|
||||
database: consuldemocracy_development
|
||||
|
||||
test:
|
||||
<<: *default
|
||||
database: consuldemocracy_test
|
||||
|
||||
production:
|
||||
<<: *default
|
||||
url: <%= ENV['DATABASE_URL'] %>
|
||||
pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 20 } %>
|
@@ -0,0 +1,39 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
echo "Initializing data directory..."
|
||||
|
||||
# Check if data directories exist, if not create them
|
||||
mkdir -p /app/data/files
|
||||
mkdir -p /app/data/images
|
||||
mkdir -p /app/data/log
|
||||
mkdir -p /app/data/tmp
|
||||
|
||||
# Generate a secret key base if it doesn't exist
|
||||
if [ ! -f /app/data/secret_key_base ]; then
|
||||
echo "Generating secret key base..."
|
||||
openssl rand -hex 64 > /app/data/secret_key_base
|
||||
chmod 600 /app/data/secret_key_base
|
||||
fi
|
||||
|
||||
# Create symlinks from app to data directory
|
||||
if [ ! -L /app/code/storage ]; then
|
||||
ln -sf /app/data/files /app/code/storage
|
||||
fi
|
||||
|
||||
if [ ! -L /app/code/public/uploads ]; then
|
||||
ln -sf /app/data/images /app/code/public/uploads
|
||||
fi
|
||||
|
||||
if [ ! -L /app/code/log ]; then
|
||||
ln -sf /app/data/log /app/code/log
|
||||
fi
|
||||
|
||||
if [ ! -L /app/code/tmp ]; then
|
||||
ln -sf /app/data/tmp /app/code/tmp
|
||||
fi
|
||||
|
||||
# Set proper permissions
|
||||
chown -R cloudron:cloudron /app/data
|
||||
|
||||
echo "Data directory initialized."
|
@@ -0,0 +1,15 @@
|
||||
production:
|
||||
enabled: true
|
||||
host: <%= ENV['LDAP_HOST'] %>
|
||||
port: <%= ENV['LDAP_PORT'] %>
|
||||
ssl: true
|
||||
admin_user: <%= ENV['LDAP_ADMIN_USER'] %>
|
||||
admin_password: <%= ENV['LDAP_ADMIN_PASSWORD'] %>
|
||||
base: <%= ENV['LDAP_BASE'] %>
|
||||
user_filter: "(uid=%{username})"
|
||||
group_base: <%= ENV['CLOUDRON_LDAP_GROUPS_BASE_DN'] %>
|
||||
required_groups:
|
||||
- <%= ENV['CLOUDRON_LDAP_GROUPS_BASE_DN'] %>
|
||||
attribute_mapping:
|
||||
email: mail
|
||||
name: displayName
|
@@ -0,0 +1,47 @@
|
||||
server {
|
||||
listen 8000;
|
||||
server_name _;
|
||||
|
||||
root /app/code/public;
|
||||
client_max_body_size 100M;
|
||||
|
||||
# Handle asset requests
|
||||
location ~ ^/(assets|packs)/ {
|
||||
expires max;
|
||||
add_header Cache-Control public;
|
||||
}
|
||||
|
||||
# Proxy requests to the Rails application
|
||||
location / {
|
||||
try_files $uri @passenger;
|
||||
}
|
||||
|
||||
location @passenger {
|
||||
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_set_header X-Forwarded-Port $server_port;
|
||||
|
||||
# Forward the original request scheme (http or https)
|
||||
proxy_set_header X-Forwarded-Proto $http_x_forwarded_proto;
|
||||
|
||||
# Needed for Cloudron authentication
|
||||
proxy_set_header X-Cloudron-Proxy-Port 8000;
|
||||
|
||||
# Proxy to the Rails application served by Puma
|
||||
proxy_pass http://unix:/run/consuldemocracy.sock;
|
||||
proxy_redirect off;
|
||||
}
|
||||
|
||||
# Error pages
|
||||
error_page 500 502 503 504 /500.html;
|
||||
error_page 404 /404.html;
|
||||
error_page 422 /422.html;
|
||||
|
||||
# Logging
|
||||
access_log /dev/stdout;
|
||||
error_log /dev/stderr;
|
||||
}
|
29
Cloudron/WorkInProgress/governance.knownelement.com/oauth.rb
Normal file
29
Cloudron/WorkInProgress/governance.knownelement.com/oauth.rb
Normal file
@@ -0,0 +1,29 @@
|
||||
# Configure OAuth integration with Cloudron
|
||||
if ENV['CLOUDRON_OIDC_IDENTIFIER'] && Rails.env.production?
|
||||
Rails.application.config.middleware.use OmniAuth::Builder do
|
||||
provider :openid_connect, {
|
||||
name: :cloudron,
|
||||
scope: [:openid, :email, :profile],
|
||||
response_type: :code,
|
||||
uid_field: 'sub',
|
||||
discovery: true,
|
||||
client_options: {
|
||||
identifier: ENV['CLOUDRON_OIDC_CLIENT_ID'],
|
||||
secret: ENV['CLOUDRON_OIDC_CLIENT_SECRET'],
|
||||
redirect_uri: "https://#{ENV['CLOUDRON_APP_DOMAIN']}/oauth/callback",
|
||||
port: 443,
|
||||
scheme: 'https',
|
||||
host: "#{ENV['CLOUDRON_APP_DOMAIN']}",
|
||||
discovery_document: ENV['CLOUDRON_OIDC_IDENTIFIER']
|
||||
},
|
||||
client_auth_method: 'secret_basic'
|
||||
}
|
||||
end
|
||||
|
||||
# Map additional user attributes from Cloudron OIDC
|
||||
OmniAuth::Strategies::OAuth2.class_eval do
|
||||
def callback_url
|
||||
full_host + script_name + callback_path
|
||||
end
|
||||
end
|
||||
end
|
@@ -0,0 +1,21 @@
|
||||
default: &default
|
||||
secret_key_base: <%= ENV["SECRET_KEY_BASE"] %>
|
||||
server_name: <%= ENV["CLOUDRON_APP_DOMAIN"] %>
|
||||
smtp_settings:
|
||||
address: <%= ENV["SMTP_ADDRESS"] %>
|
||||
port: <%= ENV["SMTP_PORT"] %>
|
||||
domain: <%= ENV["SMTP_DOMAIN"] %>
|
||||
user_name: <%= ENV["SMTP_USER_NAME"] %>
|
||||
password: <%= ENV["SMTP_PASSWORD"] %>
|
||||
authentication: "login"
|
||||
enable_starttls_auto: true
|
||||
mailer_sender: <%= "noreply@#{ENV['CLOUDRON_APP_DOMAIN']}" %>
|
||||
|
||||
development:
|
||||
<<: *default
|
||||
|
||||
test:
|
||||
<<: *default
|
||||
|
||||
production:
|
||||
<<: *default
|
45
Cloudron/WorkInProgress/governance.knownelement.com/start.sh
Normal file
45
Cloudron/WorkInProgress/governance.knownelement.com/start.sh
Normal file
@@ -0,0 +1,45 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
echo "Starting Consul Democracy..."
|
||||
|
||||
# Initialize the data directory if it doesn't exist
|
||||
/app/code/init-data.sh
|
||||
|
||||
cd /app/code
|
||||
|
||||
# Setup environment variables
|
||||
export DATABASE_URL="postgresql://${CLOUDRON_POSTGRESQL_USERNAME}:${CLOUDRON_POSTGRESQL_PASSWORD}@${CLOUDRON_POSTGRESQL_HOST}:${CLOUDRON_POSTGRESQL_PORT}/${CLOUDRON_POSTGRESQL_DATABASE}"
|
||||
export SECRET_KEY_BASE=$(cat /app/data/secret_key_base)
|
||||
export RAILS_ENV=production
|
||||
export RAILS_SERVE_STATIC_FILES=true
|
||||
export RAILS_LOG_TO_STDOUT=true
|
||||
|
||||
# Configure email settings
|
||||
export SMTP_ADDRESS=${CLOUDRON_MAIL_SMTP_SERVER}
|
||||
export SMTP_PORT=${CLOUDRON_MAIL_SMTP_PORT}
|
||||
export SMTP_DOMAIN=${CLOUDRON_APP_DOMAIN}
|
||||
export SMTP_USER_NAME=${CLOUDRON_MAIL_SMTP_USERNAME}
|
||||
export SMTP_PASSWORD=${CLOUDRON_MAIL_SMTP_PASSWORD}
|
||||
|
||||
# LDAP Setup for Cloudron integration
|
||||
export LDAP_HOST=${CLOUDRON_LDAP_SERVER}
|
||||
export LDAP_PORT=${CLOUDRON_LDAP_PORT}
|
||||
export LDAP_ADMIN_USER=${CLOUDRON_LDAP_BIND_DN}
|
||||
export LDAP_ADMIN_PASSWORD=${CLOUDRON_LDAP_BIND_PASSWORD}
|
||||
export LDAP_BASE=${CLOUDRON_LDAP_USERS_BASE_DN}
|
||||
|
||||
# Run db migrations if needed
|
||||
echo "Running database migrations..."
|
||||
bundle exec rake db:migrate
|
||||
|
||||
# Seed the database if it's the first run
|
||||
if [ ! -f /app/data/.initialized ]; then
|
||||
echo "First run detected, seeding the database..."
|
||||
bundle exec rake db:seed
|
||||
touch /app/data/.initialized
|
||||
fi
|
||||
|
||||
# Start the application server via supervisord
|
||||
echo "Starting supervisord..."
|
||||
exec /usr/bin/supervisord -c /etc/supervisor/supervisord.conf
|
@@ -0,0 +1,32 @@
|
||||
[program:nginx]
|
||||
command=/usr/sbin/nginx -g "daemon off;"
|
||||
autostart=true
|
||||
autorestart=true
|
||||
stdout_logfile=/dev/stdout
|
||||
stdout_logfile_maxbytes=0
|
||||
stderr_logfile=/dev/stderr
|
||||
stderr_logfile_maxbytes=0
|
||||
|
||||
[program:rails]
|
||||
directory=/app/code
|
||||
command=bundle exec puma -e production -b unix:///run/consuldemocracy.sock
|
||||
user=cloudron
|
||||
autostart=true
|
||||
autorestart=true
|
||||
stdout_logfile=/dev/stdout
|
||||
stdout_logfile_maxbytes=0
|
||||
stderr_logfile=/dev/stderr
|
||||
stderr_logfile_maxbytes=0
|
||||
environment=RAILS_ENV=production,RAILS_LOG_TO_STDOUT=true,RAILS_SERVE_STATIC_FILES=true
|
||||
|
||||
[program:sidekiq]
|
||||
directory=/app/code
|
||||
command=bundle exec sidekiq -e production
|
||||
user=cloudron
|
||||
autostart=true
|
||||
autorestart=true
|
||||
stdout_logfile=/dev/stdout
|
||||
stdout_logfile_maxbytes=0
|
||||
stderr_logfile=/dev/stderr
|
||||
stderr_logfile_maxbytes=0
|
||||
environment=RAILS_ENV=production,RAILS_LOG_TO_STDOUT=true
|
@@ -0,0 +1,46 @@
|
||||
{
|
||||
"id": "com.getgrist.cloudron",
|
||||
"title": "Grist",
|
||||
"author": "Grist Labs",
|
||||
"description": "A modern, open source spreadsheet that goes beyond the grid. Grist combines the flexibility of a spreadsheet with the robustness of a database to organize your data your way.",
|
||||
"tagline": "Modern relational spreadsheet with Python formulas",
|
||||
"version": "1.0.0",
|
||||
"healthCheckPath": "/healthz",
|
||||
"httpPort": 8080,
|
||||
"addons": {
|
||||
"localstorage": {},
|
||||
"postgresql": {
|
||||
"userName": "grist",
|
||||
"databaseName": "grist"
|
||||
}
|
||||
},
|
||||
"manifestVersion": 2,
|
||||
"website": "https://www.getgrist.com/",
|
||||
"documentationUrl": "https://support.getgrist.com/",
|
||||
"contactEmail": "support@getgrist.com",
|
||||
"icon": "file://logo.png",
|
||||
"memoryLimit": 1024,
|
||||
"tags": ["spreadsheet", "database", "python", "dashboard"],
|
||||
"minBoxVersion": "7.0.0",
|
||||
"installationNotes": {
|
||||
"en": "The default administrator account is set to your Cloudron email. Access Grist at the configured subdomain."
|
||||
},
|
||||
"postInstallationNotes": {
|
||||
"en": "Grist has been successfully installed. The administrator account is set to your Cloudron email. Sign in using your Cloudron account credentials."
|
||||
},
|
||||
"forumUrl": "https://community.getgrist.com/",
|
||||
"mediaLinks": [
|
||||
"https://www.getgrist.com/assets/images/grist-demo.png"
|
||||
],
|
||||
"authentication": {
|
||||
"loginPath": "/auth/login",
|
||||
"logoutPath": "/auth/logout",
|
||||
"impl": "oauth",
|
||||
"oauth": {
|
||||
"clientId": "{{cloudronOAuthClientId}}",
|
||||
"clientSecret": "{{cloudronOAuthClientSecret}}",
|
||||
"callbackPath": "/oauth2/callback",
|
||||
"scope": "profile email"
|
||||
}
|
||||
}
|
||||
}
|
79
Cloudron/WorkInProgress/grist.knownelement.com/Dockerfile
Normal file
79
Cloudron/WorkInProgress/grist.knownelement.com/Dockerfile
Normal file
@@ -0,0 +1,79 @@
|
||||
FROM cloudron/base:4.2.0
|
||||
|
||||
# Add Cloudron specific environment
|
||||
ENV CLOUDRON=1 \
|
||||
HOME=/app/data \
|
||||
LC_ALL=C.UTF-8 \
|
||||
LANG=C.UTF-8 \
|
||||
USER=cloudron \
|
||||
PORT=8080 \
|
||||
PYTHON_VERSION=3 \
|
||||
PYTHON_VERSION_ON_CREATION=3 \
|
||||
DEBUG=0
|
||||
|
||||
# Install required dependencies
|
||||
RUN apt-get update && \
|
||||
apt-get install -y --no-install-recommends \
|
||||
wget \
|
||||
gnupg \
|
||||
supervisor \
|
||||
python3 \
|
||||
python3-pip \
|
||||
python3-setuptools \
|
||||
python3-wheel \
|
||||
python3-venv \
|
||||
build-essential \
|
||||
pkg-config \
|
||||
xvfb \
|
||||
xauth \
|
||||
libcairo2-dev \
|
||||
libpango1.0-dev \
|
||||
libglib2.0-dev \
|
||||
nodejs \
|
||||
npm \
|
||||
git \
|
||||
sqlite3 \
|
||||
curl \
|
||||
ca-certificates && \
|
||||
apt-get clean && \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Create required directories
|
||||
RUN mkdir -p /app/code /app/data /app/pkg /app/log && \
|
||||
mkdir -p /app/data/docs
|
||||
|
||||
# Clone Grist
|
||||
WORKDIR /app/pkg
|
||||
RUN git clone --depth 1 https://github.com/gristlabs/grist-core.git && \
|
||||
cd grist-core && \
|
||||
npm install && \
|
||||
npm run build && \
|
||||
cd /app/pkg
|
||||
|
||||
# Set up supervisor config
|
||||
COPY supervisor.conf /etc/supervisor/conf.d/grist.conf
|
||||
COPY nginx.conf /app/pkg/nginx.conf
|
||||
|
||||
# Nginx site configuration
|
||||
COPY nginx-app.conf /etc/nginx/sites-available/grist
|
||||
RUN ln -sf /etc/nginx/sites-available/grist /etc/nginx/sites-enabled/grist && \
|
||||
rm -f /etc/nginx/sites-enabled/default
|
||||
|
||||
# Add scripts
|
||||
COPY start.sh /app/pkg/
|
||||
RUN chmod +x /app/pkg/start.sh
|
||||
|
||||
# Set up initialization data
|
||||
COPY --chown=cloudron:cloudron init_data/ /app/pkg/init_data/
|
||||
|
||||
# Set ownership
|
||||
RUN chown -R cloudron:cloudron /app/code /app/data /app/pkg /app/log
|
||||
|
||||
# Set working directory
|
||||
WORKDIR /app/pkg
|
||||
|
||||
# Run as cloudron user
|
||||
USER cloudron
|
||||
|
||||
# Start application
|
||||
CMD ["/app/pkg/start.sh"]
|
@@ -0,0 +1,131 @@
|
||||
# Grist Cloudron Package Build Notes
|
||||
|
||||
## Overview
|
||||
|
||||
This document provides instructions for building, testing, and deploying the Grist Cloudron package. Grist is a modern, open-source spreadsheet application with database capabilities, Python formulas, and collaborative features.
|
||||
|
||||
## Package Components
|
||||
|
||||
The package includes the following files:
|
||||
|
||||
1. `CloudronManifest.json` - Configuration file for Cloudron
|
||||
2. `Dockerfile` - Instructions for building the Docker image
|
||||
3. `start.sh` - Initialization and startup script
|
||||
4. `supervisor.conf` - Process management configuration
|
||||
5. `nginx-app.conf` - NGINX site configuration
|
||||
6. `nginx.conf` - NGINX main configuration
|
||||
7. `logo.png` - Grist logo for Cloudron (needs to be added)
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Cloudron server (v7.0.0 or newer)
|
||||
- Docker installed on your build machine
|
||||
- Cloudron CLI installed on your build machine
|
||||
|
||||
## Build Instructions
|
||||
|
||||
1. **Prepare the package directory**
|
||||
|
||||
Create a directory for your package and place all the files in it:
|
||||
|
||||
```bash
|
||||
mkdir -p grist-cloudron
|
||||
cd grist-cloudron
|
||||
# Copy all files into this directory
|
||||
```
|
||||
|
||||
2. **Add the Grist logo**
|
||||
|
||||
Download the Grist logo and save it as `logo.png` in the package directory:
|
||||
|
||||
```bash
|
||||
curl -o logo.png https://raw.githubusercontent.com/gristlabs/grist-core/main/static/favicon.png
|
||||
```
|
||||
|
||||
3. **Create an initialization data directory**
|
||||
|
||||
```bash
|
||||
mkdir -p init_data
|
||||
```
|
||||
|
||||
4. **Build the Docker image**
|
||||
|
||||
```bash
|
||||
cloudron build
|
||||
```
|
||||
|
||||
## Testing the Package
|
||||
|
||||
1. **Install the package on your Cloudron for testing**
|
||||
|
||||
```bash
|
||||
cloudron install —image your-docker-image-name
|
||||
```
|
||||
|
||||
2. **Verify the installation**
|
||||
|
||||
Once installed, navigate to the app’s URL and verify that:
|
||||
- The login page appears correctly
|
||||
- You can log in using your Cloudron credentials
|
||||
- You can create and edit documents
|
||||
- Document imports and exports work properly
|
||||
- Python formulas are functioning correctly
|
||||
|
||||
3. **Test authentication**
|
||||
|
||||
Verify that:
|
||||
- Authentication with Cloudron accounts works
|
||||
- User permissions are applied correctly
|
||||
- Logging out works properly
|
||||
|
||||
## Common Issues and Troubleshooting
|
||||
|
||||
1. **Authentication Issues**
|
||||
- Check that the OAuth configuration is correct in `CloudronManifest.json`
|
||||
- Verify environment variables in `start.sh` related to OIDC
|
||||
|
||||
2. **Database Connection Problems**
|
||||
- Verify PostgreSQL addon configuration
|
||||
- Check logs for database connection errors
|
||||
|
||||
3. **Grist Not Starting**
|
||||
- Check supervisord logs: `cloudron logs -f`
|
||||
- Verify that the required directories exist and have proper permissions
|
||||
|
||||
4. **File Upload Issues**
|
||||
- Verify the `client_max_body_size` setting in the NGINX configuration
|
||||
|
||||
## Deployment
|
||||
|
||||
1. **Prepare the package for production**
|
||||
|
||||
```bash
|
||||
cloudron build
|
||||
cloudron upload
|
||||
```
|
||||
|
||||
2. **Install from the Cloudron App Store**
|
||||
|
||||
After submission and approval, users can install directly from the Cloudron App Store.
|
||||
|
||||
## Maintenance
|
||||
|
||||
1. **Updating Grist**
|
||||
|
||||
To update Grist to a newer version:
|
||||
- Update the git clone command in the `Dockerfile`
|
||||
- Update the version in `CloudronManifest.json`
|
||||
- Rebuild and redeploy
|
||||
|
||||
2. **Backing Up**
|
||||
|
||||
Cloudron automatically backs up:
|
||||
- The PostgreSQL database
|
||||
- The `/app/data` directory containing all Grist documents
|
||||
|
||||
## Additional Resources
|
||||
|
||||
- [Grist Documentation](https://support.getgrist.com/)
|
||||
- [Grist GitHub Repository](https://github.com/gristlabs/grist-core)
|
||||
- [Cloudron Documentation](https://docs.cloudron.io/)
|
||||
- [Grist Community Forum](https://community.getgrist.com/)
|
@@ -0,0 +1,53 @@
|
||||
server {
|
||||
listen 8080;
|
||||
server_name localhost;
|
||||
|
||||
# Set maximum upload size
|
||||
client_max_body_size 300M;
|
||||
|
||||
# Add security headers
|
||||
add_header X-Content-Type-Options nosniff;
|
||||
add_header X-XSS-Protection "1; mode=block";
|
||||
add_header X-Frame-Options SAMEORIGIN;
|
||||
add_header Referrer-Policy strict-origin-when-cross-origin;
|
||||
|
||||
# Main location for Grist
|
||||
location / {
|
||||
proxy_pass http://127.0.0.1:8484;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "upgrade";
|
||||
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-Port $server_port;
|
||||
proxy_read_timeout 90;
|
||||
proxy_buffering off;
|
||||
}
|
||||
|
||||
# Health check endpoint
|
||||
location = /healthz {
|
||||
access_log off;
|
||||
add_header Content-Type text/plain;
|
||||
return 200 'OK';
|
||||
}
|
||||
|
||||
# Static file caching
|
||||
location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ {
|
||||
proxy_pass http://127.0.0.1:8484;
|
||||
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;
|
||||
expires 30d;
|
||||
add_header Cache-Control "public, no-transform";
|
||||
}
|
||||
|
||||
# Error pages
|
||||
error_page 500 502 503 504 /50x.html;
|
||||
location = /50x.html {
|
||||
root /usr/share/nginx/html;
|
||||
}
|
||||
}
|
43
Cloudron/WorkInProgress/grist.knownelement.com/nginx.conf
Normal file
43
Cloudron/WorkInProgress/grist.knownelement.com/nginx.conf
Normal file
@@ -0,0 +1,43 @@
|
||||
user cloudron;
|
||||
worker_processes auto;
|
||||
pid /run/nginx.pid;
|
||||
include /etc/nginx/modules-enabled/*.conf;
|
||||
|
||||
events {
|
||||
worker_connections 768;
|
||||
# multi_accept on;
|
||||
}
|
||||
|
||||
http {
|
||||
# Basic Settings
|
||||
sendfile on;
|
||||
tcp_nopush on;
|
||||
tcp_nodelay on;
|
||||
keepalive_timeout 65;
|
||||
types_hash_max_size 2048;
|
||||
|
||||
include /etc/nginx/mime.types;
|
||||
default_type application/octet-stream;
|
||||
|
||||
# SSL Settings
|
||||
ssl_protocols TLSv1.2 TLSv1.3;
|
||||
ssl_prefer_server_ciphers on;
|
||||
|
||||
# Logging Settings
|
||||
access_log /dev/stdout;
|
||||
error_log /dev/stderr;
|
||||
|
||||
# Gzip Settings
|
||||
gzip on;
|
||||
gzip_disable "msie6";
|
||||
gzip_vary on;
|
||||
gzip_proxied any;
|
||||
gzip_comp_level 6;
|
||||
gzip_buffers 16 8k;
|
||||
gzip_http_version 1.1;
|
||||
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
|
||||
|
||||
# Virtual Host Configs
|
||||
include /etc/nginx/conf.d/*.conf;
|
||||
include /etc/nginx/sites-enabled/*;
|
||||
}
|
63
Cloudron/WorkInProgress/grist.knownelement.com/start.sh
Normal file
63
Cloudron/WorkInProgress/grist.knownelement.com/start.sh
Normal file
@@ -0,0 +1,63 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
# Cloudron environment variables
|
||||
export GRIST_APP_ROOT="/app/pkg/grist-core"
|
||||
export GRIST_DATA_DIR="/app/data/docs"
|
||||
export GRIST_SESSION_SECRET="${CLOUDRON_SESSION_SECRET}"
|
||||
export APP_HOME_URL="${CLOUDRON_APP_URL}"
|
||||
export GRIST_DOMAIN="${CLOUDRON_APP_DOMAIN}"
|
||||
export GRIST_SINGLE_ORG="cloudron"
|
||||
export GRIST_HIDE_UI_ELEMENTS="billing"
|
||||
export GRIST_MAX_UPLOAD_ATTACHMENT_MB=100
|
||||
export GRIST_MAX_UPLOAD_IMPORT_MB=300
|
||||
export GRIST_SANDBOX_FLAVOR="gvisor"
|
||||
export GRIST_USER_ROOT="/app/data"
|
||||
export GRIST_THROTTLE_CPU="true"
|
||||
export GRIST_DEFAULT_EMAIL="${CLOUDRON_ADMIN_EMAIL}"
|
||||
export GRIST_FORCE_LOGIN="true"
|
||||
export GRIST_SUPPORT_ANON="false"
|
||||
export COOKIE_MAX_AGE=2592000000 # 30 days in milliseconds
|
||||
|
||||
# Setup OpenID Connect for Cloudron authentication
|
||||
export GRIST_OIDC_IDP_ISSUER="${CLOUDRON_APP_ORIGIN}"
|
||||
export GRIST_OIDC_IDP_CLIENT_ID="${CLOUDRON_OAUTH_CLIENT_ID}"
|
||||
export GRIST_OIDC_IDP_CLIENT_SECRET="${CLOUDRON_OAUTH_CLIENT_SECRET}"
|
||||
export GRIST_OIDC_IDP_SCOPES="openid profile email"
|
||||
export GRIST_OIDC_SP_HOST="${CLOUDRON_APP_URL}"
|
||||
export GRIST_OIDC_SP_PROFILE_EMAIL_ATTR="email"
|
||||
export GRIST_OIDC_SP_PROFILE_NAME_ATTR="name"
|
||||
export GRIST_OIDC_IDP_ENABLED_PROTECTIONS="PKCE,STATE"
|
||||
|
||||
# Database configuration using Cloudron PostgreSQL addon
|
||||
export TYPEORM_TYPE="postgres"
|
||||
export TYPEORM_DATABASE="${CLOUDRON_POSTGRESQL_DATABASE}"
|
||||
export TYPEORM_USERNAME="${CLOUDRON_POSTGRESQL_USERNAME}"
|
||||
export TYPEORM_PASSWORD="${CLOUDRON_POSTGRESQL_PASSWORD}"
|
||||
export TYPEORM_HOST="${CLOUDRON_POSTGRESQL_HOST}"
|
||||
export TYPEORM_PORT="${CLOUDRON_POSTGRESQL_PORT}"
|
||||
export TYPEORM_LOGGING="false"
|
||||
|
||||
# Initialize or update data directories if they don't exist
|
||||
if [ ! -d "/app/data/docs" ]; then
|
||||
mkdir -p /app/data/docs
|
||||
echo "Created docs directory"
|
||||
fi
|
||||
|
||||
if [ ! -d "/app/data/home" ]; then
|
||||
mkdir -p /app/data/home
|
||||
echo "Created home directory"
|
||||
fi
|
||||
|
||||
# Copy initialization data if needed
|
||||
if [ -d "/app/pkg/init_data" ] && [ ! -f "/app/data/.initialized" ]; then
|
||||
cp -R /app/pkg/init_data/* /app/data/
|
||||
touch /app/data/.initialized
|
||||
echo "Copied initialization data"
|
||||
fi
|
||||
|
||||
# Ensure proper permissions
|
||||
chown -R cloudron:cloudron /app/data
|
||||
|
||||
# Start supervisor to manage Grist and Nginx
|
||||
exec /usr/bin/supervisord --nodaemon -c /etc/supervisor/supervisord.conf
|
@@ -0,0 +1,32 @@
|
||||
[supervisord]
|
||||
nodaemon=true
|
||||
logfile=/app/log/supervisord.log
|
||||
logfile_maxbytes=10MB
|
||||
logfile_backups=3
|
||||
loglevel=info
|
||||
pidfile=/run/supervisord.pid
|
||||
user=cloudron
|
||||
|
||||
[program:nginx]
|
||||
command=/usr/sbin/nginx -g "daemon off;"
|
||||
priority=10
|
||||
stdout_logfile=/dev/stdout
|
||||
stdout_logfile_maxbytes=0
|
||||
stderr_logfile=/dev/stderr
|
||||
stderr_logfile_maxbytes=0
|
||||
autostart=true
|
||||
autorestart=true
|
||||
|
||||
[program:grist]
|
||||
command=bash -c "cd /app/pkg/grist-core && node sandbox/pyodide.js"
|
||||
user=cloudron
|
||||
environment=HOME=/app/data
|
||||
directory=/app/pkg/grist-core
|
||||
stdout_logfile=/dev/stdout
|
||||
stdout_logfile_maxbytes=0
|
||||
stderr_logfile=/dev/stderr
|
||||
stderr_logfile_maxbytes=0
|
||||
autostart=true
|
||||
autorestart=true
|
||||
startretries=3
|
||||
priority=20
|
@@ -0,0 +1 @@
|
||||
This directory contains template files for the application at FQDN indidicated by the parent directory. They will be processed using mo (bash mustache).
|
@@ -0,0 +1 @@
|
||||
This directory contains final docker compose files for the application at FQDN indidicated by the parent directory.
|
@@ -0,0 +1 @@
|
||||
This directory contains files from the vendor unmodified. They serve as a base for the input-files sibling directory
|
@@ -0,0 +1,38 @@
|
||||
{
|
||||
"id": "software.homebox.cloudronapp",
|
||||
"title": "Homebox",
|
||||
"author": "CloudronApp",
|
||||
"description": "Homebox is an inventory and organization system built for home users. Manage your home inventory with a simple, fast, and lightweight application.",
|
||||
"tagline": "Simple home inventory management",
|
||||
"version": "1.0.0",
|
||||
"healthCheckPath": "/",
|
||||
"httpPort": 7745,
|
||||
"addons": {
|
||||
"localstorage": {
|
||||
"description": "Data directory for Homebox"
|
||||
}
|
||||
},
|
||||
"manifestVersion": 2,
|
||||
"website": "https://homebox.software/",
|
||||
"contactEmail": "support@homebox.software",
|
||||
"icon": "file://logo.png",
|
||||
"tags": [
|
||||
"inventory",
|
||||
"organization",
|
||||
"asset-management",
|
||||
"home"
|
||||
],
|
||||
"minBoxVersion": "7.5.0",
|
||||
"documentationUrl": "https://homebox.software/en/",
|
||||
"forumUrl": "https://github.com/sysadminsmedia/homebox/discussions",
|
||||
"postInstallMessage": "Homebox has been successfully installed! The first user to register will be the administrator. You can disable registration after creating the first account.",
|
||||
"memoryLimit": 256000000,
|
||||
"targetBoxVersion": "7.5.0",
|
||||
"changelog": "Initial Cloudron package",
|
||||
"mediaLinks": [],
|
||||
"containerOptions": {
|
||||
"securityContext": {
|
||||
"allowPrivilegeEscalation": false
|
||||
}
|
||||
}
|
||||
}
|
46
Cloudron/WorkInProgress/homebox.knownelement.com/Dockerfile
Normal file
46
Cloudron/WorkInProgress/homebox.knownelement.com/Dockerfile
Normal file
@@ -0,0 +1,46 @@
|
||||
FROM cloudron/base:4.2.0
|
||||
|
||||
# Add version specifics
|
||||
ARG VERSION=latest
|
||||
ARG DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
# Update the system and install dependencies
|
||||
RUN apt-get update && \
|
||||
apt-get install -y \
|
||||
curl \
|
||||
ca-certificates \
|
||||
wget \
|
||||
&& apt-get clean && rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Set up directory structure following Cloudron filesystem layout
|
||||
RUN mkdir -p /app/code /app/data /tmp/data
|
||||
|
||||
# Set working directory
|
||||
WORKDIR /app/code
|
||||
|
||||
# Download and install the latest Homebox release
|
||||
RUN if [ "$VERSION" = "latest" ]; then \
|
||||
DOWNLOAD_URL=$(curl -s https://api.github.com/repos/sysadminsmedia/homebox/releases/latest | grep "browser_download_url.*linux_amd64" | cut -d '"' -f 4); \
|
||||
else \
|
||||
DOWNLOAD_URL="https://github.com/sysadminsmedia/homebox/releases/download/v${VERSION}/homebox_${VERSION}_linux_amd64.tar.gz"; \
|
||||
fi && \
|
||||
wget -O /tmp/homebox.tar.gz ${DOWNLOAD_URL} && \
|
||||
tar -xzf /tmp/homebox.tar.gz -C /app/code && \
|
||||
rm /tmp/homebox.tar.gz && \
|
||||
chmod +x /app/code/homebox
|
||||
|
||||
# Copy initialization template for /app/data
|
||||
COPY data_init /tmp/data/
|
||||
|
||||
# Copy application scripts
|
||||
COPY start.sh /app/code/
|
||||
RUN chmod +x /app/code/start.sh
|
||||
|
||||
# Copy NGINX configuration
|
||||
COPY nginx.conf /app/code/
|
||||
|
||||
# Set ownership to cloudron user
|
||||
RUN chown -R cloudron:cloudron /app/code /tmp/data
|
||||
|
||||
# Set entrypoint
|
||||
ENTRYPOINT ["/app/code/start.sh"]
|
67
Cloudron/WorkInProgress/homebox.knownelement.com/nginx.conf
Normal file
67
Cloudron/WorkInProgress/homebox.knownelement.com/nginx.conf
Normal file
@@ -0,0 +1,67 @@
|
||||
worker_processes auto;
|
||||
pid /run/nginx.pid;
|
||||
|
||||
events {
|
||||
worker_connections 768;
|
||||
multi_accept on;
|
||||
}
|
||||
|
||||
http {
|
||||
sendfile on;
|
||||
tcp_nopush on;
|
||||
tcp_nodelay on;
|
||||
keepalive_timeout 65;
|
||||
types_hash_max_size 2048;
|
||||
server_tokens off;
|
||||
|
||||
# Mime types
|
||||
include /etc/nginx/mime.types;
|
||||
default_type application/octet-stream;
|
||||
|
||||
# Logging
|
||||
access_log /dev/stdout;
|
||||
error_log /dev/stderr;
|
||||
|
||||
# Gzip settings
|
||||
gzip on;
|
||||
gzip_disable "msie6";
|
||||
gzip_vary on;
|
||||
gzip_proxied any;
|
||||
gzip_comp_level 6;
|
||||
gzip_buffers 16 8k;
|
||||
gzip_http_version 1.1;
|
||||
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
|
||||
|
||||
# Virtual Host Configs
|
||||
server {
|
||||
listen 8000 default_server;
|
||||
listen [::]:8000 default_server;
|
||||
|
||||
server_name _;
|
||||
|
||||
# Maximum upload size
|
||||
client_max_body_size 100M;
|
||||
|
||||
# Proxy settings
|
||||
proxy_buffers 16 16k;
|
||||
proxy_buffer_size 16k;
|
||||
|
||||
location / {
|
||||
proxy_pass http://127.0.0.1:7745;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "upgrade";
|
||||
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-Port $server_port;
|
||||
|
||||
# Set timeouts
|
||||
proxy_connect_timeout 60s;
|
||||
proxy_send_timeout 60s;
|
||||
proxy_read_timeout 300s;
|
||||
}
|
||||
}
|
||||
}
|
108
Cloudron/WorkInProgress/homebox.knownelement.com/start.sh
Normal file
108
Cloudron/WorkInProgress/homebox.knownelement.com/start.sh
Normal file
@@ -0,0 +1,108 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
# Ensure proper directory structure in /app/data
|
||||
if [ ! -d "/app/data/.database" ]; then
|
||||
echo "Initializing data directory structure..."
|
||||
mkdir -p /app/data/.database
|
||||
mkdir -p /app/data/uploads
|
||||
|
||||
# Copy initialization files if provided
|
||||
if [ -d "/tmp/data" ]; then
|
||||
cp -r /tmp/data/* /app/data/
|
||||
fi
|
||||
|
||||
# Fix permissions
|
||||
chown -R cloudron:cloudron /app/data
|
||||
chmod -R 750 /app/data
|
||||
fi
|
||||
|
||||
# Set environment variables for Homebox
|
||||
export HBOX_MODE=production
|
||||
export HBOX_STORAGE_DATA=/app/data
|
||||
export HBOX_DATABASE_DRIVER=sqlite3
|
||||
export HBOX_DATABASE_SQLITE_PATH="/app/data/.database/homebox.db"
|
||||
export HBOX_WEB_PORT=7745
|
||||
export HBOX_WEB_HOST=127.0.0.1
|
||||
export HBOX_LOG_LEVEL=info
|
||||
export HBOX_LOG_FORMAT=text
|
||||
export HBOX_WEB_MAX_FILE_UPLOAD=50
|
||||
|
||||
# Check if registration should be disabled by default
|
||||
# If this is a fresh install, we'll allow registration for first user
|
||||
if [ ! -f "/app/data/.database/homebox.db" ]; then
|
||||
export HBOX_OPTIONS_ALLOW_REGISTRATION=true
|
||||
else
|
||||
export HBOX_OPTIONS_ALLOW_REGISTRATION=false
|
||||
fi
|
||||
|
||||
# Configure NGINX
|
||||
echo "Configuring NGINX..."
|
||||
mkdir -p /run/nginx
|
||||
cat > /app/data/nginx.conf <<EOF
|
||||
worker_processes auto;
|
||||
daemon off;
|
||||
pid /run/nginx/nginx.pid;
|
||||
|
||||
events {
|
||||
worker_connections 1024;
|
||||
}
|
||||
|
||||
http {
|
||||
include /etc/nginx/mime.types;
|
||||
default_type application/octet-stream;
|
||||
|
||||
client_max_body_size 50M;
|
||||
|
||||
# Logging to stdout for Cloudron to capture
|
||||
access_log /dev/stdout;
|
||||
error_log /dev/stderr;
|
||||
|
||||
server {
|
||||
listen 8000;
|
||||
server_name localhost;
|
||||
|
||||
location / {
|
||||
proxy_pass http://127.0.0.1:7745;
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
EOF
|
||||
|
||||
# Start Supervisor which will manage our processes
|
||||
echo "Starting supervisor..."
|
||||
cat > /etc/supervisor/conf.d/homebox.conf <<EOF
|
||||
[supervisord]
|
||||
nodaemon=true
|
||||
logfile=/dev/null
|
||||
logfile_maxbytes=0
|
||||
|
||||
[program:homebox]
|
||||
command=/app/code/homebox
|
||||
directory=/app/code
|
||||
stdout_logfile=/dev/stdout
|
||||
stdout_logfile_maxbytes=0
|
||||
stderr_logfile=/dev/stderr
|
||||
stderr_logfile_maxbytes=0
|
||||
user=cloudron
|
||||
autostart=true
|
||||
autorestart=true
|
||||
priority=10
|
||||
|
||||
[program:nginx]
|
||||
command=nginx -c /app/data/nginx.conf
|
||||
stdout_logfile=/dev/stdout
|
||||
stdout_logfile_maxbytes=0
|
||||
stderr_logfile=/dev/stderr
|
||||
stderr_logfile_maxbytes=0
|
||||
autostart=true
|
||||
autorestart=true
|
||||
priority=20
|
||||
EOF
|
||||
|
||||
# Start supervisor
|
||||
exec /usr/bin/supervisord -c /etc/supervisor/supervisord.conf
|
@@ -0,0 +1,40 @@
|
||||
{
|
||||
"id": "app.homechart.cloudron",
|
||||
"title": "HomeChart",
|
||||
"author": "HomeChart Package Maintainer",
|
||||
"description": "Your all-in-one household management platform. Organize calendars, budgets, shopping lists, and more in one place. Enjoy features like shared calendars, meal planning, task management, and multilingual support. Secure, private, and ad-free.",
|
||||
"tagline": "Your Family's Mission Control",
|
||||
"version": "1.0.0",
|
||||
"upstreamVersion": "2024.09.0",
|
||||
"healthCheckPath": "/",
|
||||
"httpPort": 3000,
|
||||
"memoryLimit": 512,
|
||||
"addons": {
|
||||
"localstorage": {},
|
||||
"postgresql": {
|
||||
"version": "16"
|
||||
}
|
||||
},
|
||||
"tags": [
|
||||
"household",
|
||||
"family",
|
||||
"organization",
|
||||
"calendar",
|
||||
"budget",
|
||||
"tasks"
|
||||
],
|
||||
"postInstallMessage": "HomeChart has been installed successfully! You can now access your family's mission control panel.\n\nThe default administrator credentials are:\nUsername: admin@example.com\nPassword: changeme\n\nPlease login and change these credentials immediately.",
|
||||
"manifestVersion": 2,
|
||||
"website": "https://homechart.app/",
|
||||
"contactEmail": "support@example.com",
|
||||
"icon": "file://logo.png",
|
||||
"minBoxVersion": "5.4.0",
|
||||
"forumUrl": "https://forum.cloudron.io/",
|
||||
"documentationUrl": "https://homechart.app/docs/",
|
||||
"changelog": "Initial Cloudron package for HomeChart",
|
||||
"configurePath": "/settings",
|
||||
"oauth": {
|
||||
"loginRedirectUri": "/oidc",
|
||||
"scope": "openid email profile"
|
||||
}
|
||||
}
|
@@ -0,0 +1,45 @@
|
||||
FROM cloudron/base:4.2.0
|
||||
|
||||
# Install required dependencies
|
||||
RUN apt-get update && \
|
||||
apt-get install -y --no-install-recommends \
|
||||
ca-certificates \
|
||||
curl \
|
||||
supervisor \
|
||||
nginx \
|
||||
tzdata \
|
||||
gosu && \
|
||||
apt-get clean && \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Create the application directory structure
|
||||
RUN mkdir -p /app/code /app/data /run/nginx
|
||||
|
||||
# Create homechart data directories structure
|
||||
RUN mkdir -p /tmp/data
|
||||
|
||||
# Download the latest HomeChart release
|
||||
RUN curl -L -o /app/code/homechart.tar.gz https://github.com/candiddev/homechart/releases/latest/download/homechart_linux_amd64.tar.gz && \
|
||||
tar -xzf /app/code/homechart.tar.gz -C /app/code && \
|
||||
rm /app/code/homechart.tar.gz && \
|
||||
mv /app/code/homechart_linux_amd64 /app/code/homechart && \
|
||||
chmod +x /app/code/homechart
|
||||
|
||||
# Add NGINX configuration
|
||||
COPY nginx.conf /etc/nginx/sites-enabled/homechart.conf
|
||||
RUN rm -f /etc/nginx/sites-enabled/default
|
||||
|
||||
# Add Supervisor configuration
|
||||
COPY supervisor.conf /etc/supervisor/conf.d/homechart.conf
|
||||
|
||||
# Add the startup script
|
||||
COPY start.sh /app/code/
|
||||
RUN chmod +x /app/code/start.sh
|
||||
|
||||
# Set permissions
|
||||
RUN chown -R cloudron:cloudron /app/code /app/data /run/nginx
|
||||
|
||||
# Expose the port (should match the httpPort in the CloudronManifest.json)
|
||||
EXPOSE 3000
|
||||
|
||||
CMD ["/app/code/start.sh"]
|
@@ -0,0 +1,107 @@
|
||||
# HomeChart Cloudron Package - Build Notes
|
||||
|
||||
This document provides instructions for building, testing, and deploying the HomeChart Cloudron package.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
1. A running Cloudron instance
|
||||
2. Docker installed on your local machine
|
||||
3. Cloudron CLI tool installed (`npm install -g cloudron`)
|
||||
4. Git for cloning the repository
|
||||
|
||||
## Files Overview
|
||||
|
||||
- **CloudronManifest.json**: Contains metadata and configuration for the Cloudron app
|
||||
- **Dockerfile**: Defines how to build the Docker image for HomeChart
|
||||
- **start.sh**: Startup script that handles initialization and configuration
|
||||
- **nginx.conf**: NGINX configuration for proxying requests
|
||||
- **supervisor.conf**: Supervisor configuration for process management
|
||||
|
||||
## Building and Deploying
|
||||
|
||||
### Step 1: Clone the repository
|
||||
|
||||
```bash
|
||||
git clone https://github.com/yourusername/homechart-cloudron.git
|
||||
cd homechart-cloudron
|
||||
```
|
||||
|
||||
### Step 2: Build the Docker image
|
||||
|
||||
```bash
|
||||
# Login to Docker Hub if not already logged in
|
||||
docker login
|
||||
|
||||
# Build the image
|
||||
cloudron build
|
||||
```
|
||||
|
||||
When prompted, enter a repository name in the format `username/homechart` where `username` is your Docker Hub username.
|
||||
|
||||
### Step 3: Install on your Cloudron
|
||||
|
||||
```bash
|
||||
# Install the app
|
||||
cloudron install —image username/homechart:latest
|
||||
```
|
||||
|
||||
You’ll be prompted to select a subdomain for the app.
|
||||
|
||||
### Step 4: Configure the app
|
||||
|
||||
After installation, you’ll need to:
|
||||
|
||||
1. Log in using the default credentials provided in the post-install message
|
||||
2. Change the default administrator password
|
||||
3. Set up your household and invite family members
|
||||
|
||||
## Updating the App
|
||||
|
||||
To update the app after making changes:
|
||||
|
||||
```bash
|
||||
# Rebuild the Docker image
|
||||
cloudron build
|
||||
|
||||
# Update the installed app
|
||||
cloudron update —app homechart
|
||||
```
|
||||
|
||||
## Authentication
|
||||
|
||||
HomeChart is configured to use Cloudron’s OIDC provider for authentication. Users from your Cloudron instance can log in to HomeChart using their Cloudron credentials.
|
||||
|
||||
## Data Persistence
|
||||
|
||||
All HomeChart data is stored in:
|
||||
- PostgreSQL database (managed by Cloudron)
|
||||
- `/app/data` directory (backed up by Cloudron)
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### View logs
|
||||
|
||||
```bash
|
||||
cloudron logs -f —app homechart
|
||||
```
|
||||
|
||||
### Database access
|
||||
|
||||
To access the PostgreSQL database directly:
|
||||
|
||||
```bash
|
||||
cloudron exec —app homechart
|
||||
psql -U “$CLOUDRON_POSTGRESQL_USERNAME” -h “$CLOUDRON_POSTGRESQL_HOST” “$CLOUDRON_POSTGRESQL_DATABASE”
|
||||
```
|
||||
|
||||
### Common Issues
|
||||
|
||||
- **OIDC configuration issues**: Ensure the Cloudron environment variables are correctly passed to the app
|
||||
- **Database connection errors**: Check PostgreSQL connection details in the app config
|
||||
- **Memory limits**: If the app crashes due to memory issues, increase the memory limit in the CloudronManifest.json
|
||||
|
||||
## Resources
|
||||
|
||||
- [HomeChart Documentation](https://homechart.app/docs/)
|
||||
- [Cloudron Documentation](https://docs.cloudron.io/)
|
||||
- [HomeChart GitHub Repository](https://github.com/candiddev/homechart)
|
@@ -0,0 +1,42 @@
|
||||
server {
|
||||
listen 3000;
|
||||
server_name localhost;
|
||||
|
||||
# Add proper headers for running behind Cloudron's proxy
|
||||
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;
|
||||
|
||||
client_max_body_size 100M;
|
||||
|
||||
# Custom Cloudron error pages
|
||||
error_page 403 /error/403.html;
|
||||
error_page 404 /error/404.html;
|
||||
error_page 50x /error/50x.html;
|
||||
location ^~ /error/ {
|
||||
alias /app/code/public/error/;
|
||||
internal;
|
||||
}
|
||||
|
||||
# Use Cloudron's runtime directory for nginx (read-only filesystem)
|
||||
client_body_temp_path /run/nginx/body;
|
||||
proxy_temp_path /run/nginx/proxy;
|
||||
fastcgi_temp_path /run/nginx/fastcgi;
|
||||
uwsgi_temp_path /run/nginx/uwsgi;
|
||||
scgi_temp_path /run/nginx/scgi;
|
||||
|
||||
location / {
|
||||
proxy_pass http://127.0.0.1:8000;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "upgrade";
|
||||
proxy_read_timeout 86400;
|
||||
}
|
||||
|
||||
# Needed for Cloudron's health checks
|
||||
location = /healthcheck {
|
||||
access_log off;
|
||||
return 200;
|
||||
}
|
||||
}
|
53
Cloudron/WorkInProgress/homechart.knownelement.com/start.sh
Normal file
53
Cloudron/WorkInProgress/homechart.knownelement.com/start.sh
Normal file
@@ -0,0 +1,53 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
# Create required runtime directories
|
||||
mkdir -p /run/nginx/body /run/nginx/proxy /run/nginx/fastcgi /run/nginx/uwsgi /run/nginx/scgi
|
||||
chown -R cloudron:cloudron /run/nginx
|
||||
|
||||
# Initialize data directory if not existing
|
||||
if [ ! -d "/app/data/config" ]; then
|
||||
mkdir -p /app/data/config
|
||||
chown -R cloudron:cloudron /app/data
|
||||
fi
|
||||
|
||||
# Configuration
|
||||
CONFIG_FILE="/app/data/config/homechart.json"
|
||||
if [ ! -f "$CONFIG_FILE" ]; then
|
||||
echo "Creating initial configuration file..."
|
||||
cat > "$CONFIG_FILE" <<EOL
|
||||
{
|
||||
"app": {
|
||||
"baseURL": "${CLOUDRON_APP_ORIGIN}",
|
||||
"proxyAddr": "127.0.0.1, 172.18.0.1"
|
||||
},
|
||||
"postgresql": {
|
||||
"hostname": "${CLOUDRON_POSTGRESQL_HOST}",
|
||||
"username": "${CLOUDRON_POSTGRESQL_USERNAME}",
|
||||
"password": "${CLOUDRON_POSTGRESQL_PASSWORD}",
|
||||
"database": "${CLOUDRON_POSTGRESQL_DATABASE}"
|
||||
},
|
||||
"oidc": {
|
||||
"cloudron": {
|
||||
"clientID": "${CLOUDRON_OIDC_CLIENT_ID}",
|
||||
"clientSecret": "${CLOUDRON_OIDC_CLIENT_SECRET}",
|
||||
"displayName": "Cloudron",
|
||||
"oidcIssuerURL": "${CLOUDRON_OIDC_ISSUER}"
|
||||
}
|
||||
},
|
||||
"logging": {
|
||||
"level": "info"
|
||||
}
|
||||
}
|
||||
EOL
|
||||
chown cloudron:cloudron "$CONFIG_FILE"
|
||||
fi
|
||||
|
||||
# Link HomeChart configuration
|
||||
export HOMECHART_CONFIG_FILE="$CONFIG_FILE"
|
||||
|
||||
# Set the port for HomeChart to run on (internal port)
|
||||
export HOMECHART_APP_PORT=8000
|
||||
|
||||
# Start supervisor which manages nginx and homechart
|
||||
exec /usr/bin/supervisord --configuration /etc/supervisor/supervisord.conf
|
@@ -0,0 +1,28 @@
|
||||
[supervisord]
|
||||
nodaemon=true
|
||||
logfile=/dev/null
|
||||
logfile_maxbytes=0
|
||||
pidfile=/var/run/supervisord.pid
|
||||
|
||||
[program:nginx]
|
||||
priority=10
|
||||
command=nginx -g "daemon off;"
|
||||
autostart=true
|
||||
autorestart=true
|
||||
stdout_logfile=/dev/stdout
|
||||
stdout_logfile_maxbytes=0
|
||||
stderr_logfile=/dev/stderr
|
||||
stderr_logfile_maxbytes=0
|
||||
|
||||
[program:homechart]
|
||||
priority=20
|
||||
directory=/app/code
|
||||
command=/app/code/homechart
|
||||
user=cloudron
|
||||
autostart=true
|
||||
autorestart=true
|
||||
stdout_logfile=/dev/stdout
|
||||
stdout_logfile_maxbytes=0
|
||||
stderr_logfile=/dev/stderr
|
||||
stderr_logfile_maxbytes=0
|
||||
environment=HOME="/app/data"
|
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"id": "org.inventree.cloudronapp",
|
||||
"title": "InvenTree",
|
||||
"author": "Your Name",
|
||||
"description": "InvenTree is an open-source inventory management system which provides intuitive parts management and stock control.",
|
||||
"tagline": "Open Source Inventory Management System",
|
||||
"version": "1.0.0",
|
||||
"healthCheckPath": "/",
|
||||
"httpPort": 8000,
|
||||
"manifestVersion": 2,
|
||||
"website": "https://inventree.org",
|
||||
"contactEmail": "your.email@example.com",
|
||||
"icon": "logo.png",
|
||||
"documentationUrl": "https://docs.inventree.org",
|
||||
"memoryLimit": 1024000000,
|
||||
"configurePath": "/admin",
|
||||
"minBoxVersion": "7.0.0",
|
||||
"changelog": "Initial version",
|
||||
"addons": {
|
||||
"localstorage": {},
|
||||
"postgresql": {}
|
||||
},
|
||||
"postInstallMessage": "InvenTree has been installed. The default admin credentials are:\n\nUsername: admin\nPassword: admin\n\nPlease change the admin password after your first login."
|
||||
}
|
@@ -0,0 +1,74 @@
|
||||
FROM cloudron/base:4.2.0
|
||||
|
||||
# Set environment variables
|
||||
ENV PYTHONUNBUFFERED=1 \
|
||||
DEBIAN_FRONTEND=noninteractive \
|
||||
INVENTREE_HOME=/app/data \
|
||||
INVENTREE_MEDIA_ROOT=/app/data/media \
|
||||
INVENTREE_STATIC_ROOT=/app/data/static \
|
||||
INVENTREE_SECRET_KEY_FILE=/app/data/secret_key.txt \
|
||||
INVENTREE_PLUGINS_ENABLED=true \
|
||||
INVENTREE_PLUGINS_DIR=/app/data/plugins \
|
||||
INVENTREE_ADMIN_USER=admin \
|
||||
INVENTREE_ADMIN_PASSWORD=admin \
|
||||
INVENTREE_ADMIN_EMAIL=admin@example.com
|
||||
|
||||
# Install required packages
|
||||
RUN apt-get update && apt-get install -y \
|
||||
python3 \
|
||||
python3-pip \
|
||||
python3-dev \
|
||||
python3-venv \
|
||||
build-essential \
|
||||
libpq-dev \
|
||||
git \
|
||||
nginx \
|
||||
supervisor \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Setup nginx for Cloudron
|
||||
RUN rm /etc/nginx/sites-enabled/* \
|
||||
&& sed -e 's,^ErrorLog.*,ErrorLog "/dev/stderr",' -i /etc/nginx/nginx.conf \
|
||||
&& echo "daemon off;" >> /etc/nginx/nginx.conf
|
||||
|
||||
# Create InvenTree directories
|
||||
RUN mkdir -p /app/code \
|
||||
&& mkdir -p /tmp/data/media \
|
||||
&& mkdir -p /tmp/data/static \
|
||||
&& mkdir -p /tmp/data/plugins \
|
||||
&& mkdir -p /tmp/data/env \
|
||||
&& mkdir -p /tmp/data/config
|
||||
|
||||
# Create Python virtual environment
|
||||
RUN python3 -m venv /app/code/env
|
||||
|
||||
# Clone InvenTree source code
|
||||
RUN git clone --depth 1 https://github.com/inventree/InvenTree.git /app/code/inventree
|
||||
|
||||
# Install InvenTree requirements
|
||||
WORKDIR /app/code/inventree
|
||||
RUN /app/code/env/bin/pip install --upgrade pip \
|
||||
&& /app/code/env/bin/pip install wheel \
|
||||
&& /app/code/env/bin/pip install --no-cache-dir -r requirements.txt \
|
||||
&& /app/code/env/bin/pip install psycopg2 gunicorn
|
||||
|
||||
# Create default configuration files
|
||||
COPY config.yaml /tmp/data/config/config.yaml
|
||||
COPY nginx.conf /etc/nginx/sites-available/inventree
|
||||
RUN ln -s /etc/nginx/sites-available/inventree /etc/nginx/sites-enabled/
|
||||
|
||||
# Copy supervisor configuration
|
||||
COPY supervisord.conf /etc/supervisor/conf.d/supervisord.conf
|
||||
|
||||
# Add startup script
|
||||
COPY start.sh /app/code/start.sh
|
||||
RUN chmod +x /app/code/start.sh
|
||||
|
||||
# Setup NGINX runtime directory
|
||||
RUN mkdir -p /run/nginx \
|
||||
&& chown -R cloudron:cloudron /run/nginx
|
||||
|
||||
# Expose port
|
||||
EXPOSE 8000
|
||||
|
||||
CMD ["/app/code/start.sh"]
|
@@ -0,0 +1,74 @@
|
||||
# InvenTree Cloudron Build Notes
|
||||
|
||||
## Package Contents
|
||||
- CloudronManifest.json - App metadata and resource configuration
|
||||
- Dockerfile - Container build instructions
|
||||
- start.sh - App initialization and startup script
|
||||
- config.yaml - InvenTree configuration template
|
||||
- nginx.conf - Web server configuration
|
||||
- supervisord.conf - Process management configuration
|
||||
|
||||
## Build & Deploy Steps
|
||||
|
||||
### 1. Prepare Local Directory
|
||||
```bash
|
||||
mkdir -p inventree-cloudron
|
||||
cd inventree-cloudron
|
||||
# Copy all files into this directory
|
||||
```
|
||||
|
||||
### 2. Build & Push to Gitea Registry
|
||||
```bash
|
||||
# Login to your Gitea Docker registry
|
||||
docker login gitea.yourdomain.com
|
||||
|
||||
# Build the Docker image
|
||||
docker build -t gitea.yourdomain.com/yourusername/inventree:1.0.0 .
|
||||
|
||||
# Push the image to your registry
|
||||
docker push gitea.yourdomain.com/yourusername/inventree:1.0.0
|
||||
```
|
||||
|
||||
### 3. Install on Cloudron
|
||||
```bash
|
||||
# Login to your Cloudron
|
||||
cloudron login my.cloudron.example
|
||||
|
||||
# Install the app
|
||||
cloudron install --image gitea.yourdomain.com/yourusername/inventree:1.0.0
|
||||
```
|
||||
|
||||
### 4. Update Process
|
||||
```bash
|
||||
# Build with new version tag
|
||||
docker build -t gitea.yourdomain.com/yourusername/inventree:1.0.1 .
|
||||
docker push gitea.yourdomain.com/yourusername/inventree:1.0.1
|
||||
|
||||
# Update existing installation
|
||||
cloudron update --app inventree.my.cloudron.example --image gitea.yourdomain.com/yourusername/inventree:1.0.1
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Database Issues
|
||||
If database migrations fail:
|
||||
```bash
|
||||
cloudron exec --app inventree.my.cloudron.example -- /app/code/env/bin/python /app/code/inventree/manage.py migrate
|
||||
```
|
||||
|
||||
### Inspect Logs
|
||||
```bash
|
||||
cloudron logs --app inventree.my.cloudron.example
|
||||
```
|
||||
|
||||
### Debug Mode
|
||||
```bash
|
||||
cloudron debug --app inventree.my.cloudron.example
|
||||
```
|
||||
|
||||
## Initial Access
|
||||
After installation, access InvenTree at your configured domain with:
|
||||
- Username: admin
|
||||
- Password: admin
|
||||
|
||||
**Important**: Change this password immediately after first login!
|
@@ -0,0 +1,49 @@
|
||||
# InvenTree configuration file for Cloudron
|
||||
# Refer to InvenTree documentation for detailed configuration options
|
||||
|
||||
# Database connection settings will be provided via environment variables
|
||||
|
||||
# General settings
|
||||
debug: False
|
||||
log_level: WARNING
|
||||
|
||||
# Secret key will be stored in a file
|
||||
secret_key_file: /app/data/secret_key.txt
|
||||
|
||||
# Plugin settings
|
||||
plugins:
|
||||
enabled: True
|
||||
plugin_dir: /app/data/plugins
|
||||
|
||||
# File storage locations
|
||||
media_root: /app/data/media
|
||||
static_root: /app/data/static
|
||||
|
||||
# Email settings - adjust with your Cloudron email settings if needed
|
||||
email:
|
||||
host: localhost
|
||||
port: 25
|
||||
tls: false
|
||||
ssl: false
|
||||
sender: inventree@localhost
|
||||
|
||||
# Login settings
|
||||
login:
|
||||
default_protocol: https
|
||||
allow_unverified_signup: False
|
||||
allow_signup: True
|
||||
signup_email_verification: False
|
||||
login_confirm_days: 3
|
||||
password_reset_timeout_days: 3
|
||||
|
||||
# Display settings
|
||||
customization:
|
||||
instance_name: InvenTree
|
||||
default_currency: USD
|
||||
base_url: "" # Will be set by environment variable in start.sh
|
||||
|
||||
# Server settings
|
||||
server:
|
||||
workers: 2
|
||||
allowed_hosts:
|
||||
- '*' # Cloudron handles this
|
@@ -0,0 +1,35 @@
|
||||
server {
|
||||
listen 8000; # This should match the httpPort in CloudronManifest.json
|
||||
|
||||
client_max_body_size 100M;
|
||||
|
||||
access_log /dev/stdout;
|
||||
error_log /dev/stderr;
|
||||
|
||||
# Serve static files
|
||||
location /static/ {
|
||||
alias /app/data/static/;
|
||||
expires 30d;
|
||||
add_header Pragma public;
|
||||
add_header Cache-Control "public";
|
||||
}
|
||||
|
||||
# Serve media files
|
||||
location /media/ {
|
||||
alias /app/data/media/;
|
||||
expires 30d;
|
||||
add_header Pragma public;
|
||||
add_header Cache-Control "public";
|
||||
}
|
||||
|
||||
# Proxy requests to gunicorn
|
||||
location / {
|
||||
proxy_pass http://127.0.0.1:8001;
|
||||
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_redirect off;
|
||||
proxy_buffering off;
|
||||
}
|
||||
}
|
72
Cloudron/WorkInProgress/inventree.knownelement.com/start.sh
Normal file
72
Cloudron/WorkInProgress/inventree.knownelement.com/start.sh
Normal file
@@ -0,0 +1,72 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
# PostgreSQL configuration from Cloudron environment variables
|
||||
if [ -n "${CLOUDRON_POSTGRESQL_HOST}" ]; then
|
||||
export INVENTREE_DB_ENGINE="postgresql"
|
||||
export INVENTREE_DB_NAME="${CLOUDRON_POSTGRESQL_DATABASE}"
|
||||
export INVENTREE_DB_USER="${CLOUDRON_POSTGRESQL_USERNAME}"
|
||||
export INVENTREE_DB_PASSWORD="${CLOUDRON_POSTGRESQL_PASSWORD}"
|
||||
export INVENTREE_DB_HOST="${CLOUDRON_POSTGRESQL_HOST}"
|
||||
export INVENTREE_DB_PORT="${CLOUDRON_POSTGRESQL_PORT}"
|
||||
else
|
||||
echo "PostgreSQL addon not configured!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Ensure data directories exist
|
||||
if [ ! -d "${INVENTREE_HOME}/media" ]; then
|
||||
echo "Creating media directory..."
|
||||
mkdir -p "${INVENTREE_HOME}/media"
|
||||
cp -rn /tmp/data/media/* "${INVENTREE_HOME}/media/" || true
|
||||
fi
|
||||
|
||||
if [ ! -d "${INVENTREE_HOME}/static" ]; then
|
||||
echo "Creating static directory..."
|
||||
mkdir -p "${INVENTREE_HOME}/static"
|
||||
cp -rn /tmp/data/static/* "${INVENTREE_HOME}/static/" || true
|
||||
fi
|
||||
|
||||
if [ ! -d "${INVENTREE_HOME}/plugins" ]; then
|
||||
echo "Creating plugins directory..."
|
||||
mkdir -p "${INVENTREE_HOME}/plugins"
|
||||
cp -rn /tmp/data/plugins/* "${INVENTREE_HOME}/plugins/" || true
|
||||
fi
|
||||
|
||||
if [ ! -d "${INVENTREE_HOME}/config" ]; then
|
||||
echo "Creating config directory..."
|
||||
mkdir -p "${INVENTREE_HOME}/config"
|
||||
cp -rn /tmp/data/config/* "${INVENTREE_HOME}/config/" || true
|
||||
fi
|
||||
|
||||
# Generate secret key if it doesn't exist
|
||||
if [ ! -f "${INVENTREE_SECRET_KEY_FILE}" ]; then
|
||||
echo "Generating secret key..."
|
||||
python3 -c "from django.core.management.utils import get_random_secret_key; print(get_random_secret_key())" > "${INVENTREE_SECRET_KEY_FILE}"
|
||||
fi
|
||||
|
||||
cd /app/code/inventree
|
||||
|
||||
# Set InvenTree base URL (from Cloudron environment)
|
||||
export INVENTREE_BASE_URL="https://${CLOUDRON_APP_DOMAIN}"
|
||||
|
||||
# Apply database migrations and collect static files
|
||||
echo "Applying database migrations..."
|
||||
/app/code/env/bin/python manage.py migrate --noinput
|
||||
|
||||
echo "Collecting static files..."
|
||||
/app/code/env/bin/python manage.py collectstatic --noinput
|
||||
|
||||
# Create superuser if not exists
|
||||
echo "Checking for superuser..."
|
||||
DJANGO_SUPERUSER_PASSWORD="${INVENTREE_ADMIN_PASSWORD}" \
|
||||
/app/code/env/bin/python manage.py createsuperuser --noinput \
|
||||
--username "${INVENTREE_ADMIN_USER}" \
|
||||
--email "${INVENTREE_ADMIN_EMAIL}" || true
|
||||
|
||||
# Set proper permissions
|
||||
chown -R cloudron:cloudron "${INVENTREE_HOME}"
|
||||
|
||||
# Start supervisor to manage processes
|
||||
echo "Starting supervisor..."
|
||||
exec /usr/bin/supervisord -c /etc/supervisor/supervisord.conf
|
@@ -0,0 +1,26 @@
|
||||
[supervisord]
|
||||
nodaemon=true
|
||||
user=root
|
||||
logfile=/dev/stdout
|
||||
logfile_maxbytes=0
|
||||
|
||||
[program:gunicorn]
|
||||
command=/app/code/env/bin/gunicorn InvenTree.wsgi --bind 127.0.0.1:8001 --workers 2 --timeout 60 --preload --forwarded-allow-ips='*'
|
||||
directory=/app/code/inventree
|
||||
user=cloudron
|
||||
autostart=true
|
||||
autorestart=true
|
||||
stdout_logfile=/dev/stdout
|
||||
stdout_logfile_maxbytes=0
|
||||
stderr_logfile=/dev/stderr
|
||||
stderr_logfile_maxbytes=0
|
||||
environment=PYTHONUNBUFFERED=1,INVENTREE_CONFIG_FILE=/app/data/config/config.yaml
|
||||
|
||||
[program:nginx]
|
||||
command=/usr/sbin/nginx
|
||||
autostart=true
|
||||
autorestart=true
|
||||
stdout_logfile=/dev/stdout
|
||||
stdout_logfile_maxbytes=0
|
||||
stderr_logfile=/dev/stderr
|
||||
stderr_logfile_maxbytes=0
|
@@ -0,0 +1,40 @@
|
||||
{
|
||||
"id": "io.jenkins.cloudron",
|
||||
"title": "Jenkins",
|
||||
"author": "Cloudron Packager",
|
||||
"description": "Jenkins is an open source automation server which enables developers to reliably build, test, and deploy their software.",
|
||||
"tagline": "The leading open source automation server",
|
||||
"version": "1.0.0",
|
||||
"healthCheckPath": "/login",
|
||||
"httpPort": 8080,
|
||||
"manifestVersion": 2,
|
||||
"website": "https://jenkins.io/",
|
||||
"contactEmail": "support@cloudron.io",
|
||||
"icon": "file://logo.png",
|
||||
"dockerImage": "cloudron/jenkins",
|
||||
"memoryLimit": 2048000000,
|
||||
"addons": {
|
||||
"localstorage": {
|
||||
"title": "Jenkins Data"
|
||||
}
|
||||
},
|
||||
"optionalAddons": {
|
||||
"ldap": {
|
||||
"title": "LDAP Integration",
|
||||
"description": "Allow users to login with LDAP credentials"
|
||||
},
|
||||
"oauth": {
|
||||
"title": "OAuth Integration",
|
||||
"description": "Allow users to login with Cloudron credentials"
|
||||
}
|
||||
},
|
||||
"tags": [
|
||||
"ci",
|
||||
"cd",
|
||||
"devops",
|
||||
"automation"
|
||||
],
|
||||
"postInstallMessage": "Jenkins is now installed. The initial admin password is shown in the logs. You can view it by running 'cloudron logs -f'. The password is displayed after 'Jenkins initial setup is required.' in the logs.",
|
||||
"minBoxVersion": "5.4.0",
|
||||
"documentationUrl": "https://jenkins.io/doc/"
|
||||
}
|
49
Cloudron/WorkInProgress/jenkins.knownelement.com/Dockerfile
Normal file
49
Cloudron/WorkInProgress/jenkins.knownelement.com/Dockerfile
Normal file
@@ -0,0 +1,49 @@
|
||||
FROM cloudron/base:4.2.0
|
||||
|
||||
# Add Jenkins repository key and repository
|
||||
RUN apt-get update && \
|
||||
apt-get install -y gnupg curl software-properties-common && \
|
||||
curl -fsSL https://pkg.jenkins.io/debian-stable/jenkins.io-2023.key | gpg --dearmor -o /usr/share/keyrings/jenkins-keyring.gpg && \
|
||||
echo deb [signed-by=/usr/share/keyrings/jenkins-keyring.gpg] https://pkg.jenkins.io/debian-stable binary/ > /etc/apt/sources.list.d/jenkins.list
|
||||
|
||||
# Install Jenkins and required dependencies
|
||||
RUN apt-get update && \
|
||||
apt-get install -y openjdk-17-jdk jenkins fontconfig && \
|
||||
apt-get clean && \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Install required plugins for Cloudron integration
|
||||
RUN mkdir -p /tmp/data/plugins && \
|
||||
cd /tmp/data/plugins && \
|
||||
curl -L -o ldap.hpi https://updates.jenkins.io/latest/ldap.hpi && \
|
||||
curl -L -o oic-auth.hpi https://updates.jenkins.io/latest/oic-auth.hpi && \
|
||||
curl -L -o configuration-as-code.hpi https://updates.jenkins.io/latest/configuration-as-code.hpi && \
|
||||
curl -L -o credentials.hpi https://updates.jenkins.io/latest/credentials.hpi && \
|
||||
chmod 644 *.hpi
|
||||
|
||||
# Create template for casc.yaml
|
||||
RUN mkdir -p /tmp/data/casc_configs
|
||||
COPY casc_templates/ /tmp/data/casc_configs/
|
||||
|
||||
# Set up directory structure for Cloudron
|
||||
RUN mkdir -p /app/data && \
|
||||
mkdir -p /tmp/data/jenkins_home
|
||||
|
||||
# Copy startup script
|
||||
COPY start.sh /app/code/
|
||||
RUN chmod +x /app/code/start.sh
|
||||
|
||||
# Copy NGINX configuration
|
||||
COPY nginx.conf /app/code/
|
||||
|
||||
# Copy supervisor configuration
|
||||
COPY supervisor.conf /etc/supervisor/conf.d/
|
||||
|
||||
# Use the cloudron user for Jenkins
|
||||
RUN usermod -a -G jenkins cloudron && \
|
||||
chown -R cloudron:cloudron /tmp/data
|
||||
|
||||
WORKDIR /app/data
|
||||
|
||||
# Entry point
|
||||
CMD ["/app/code/start.sh"]
|
@@ -0,0 +1,97 @@
|
||||
# Jenkins for Cloudron - Build Notes
|
||||
|
||||
This document provides instructions for building, testing, and deploying the Jenkins package to Cloudron.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Cloudron server (version 5.4.0 or higher)
|
||||
- Docker installed on your build machine
|
||||
- Cloudron CLI tool installed (`npm install -g cloudron`)
|
||||
|
||||
## File Structure
|
||||
|
||||
```
|
||||
jenkins-cloudron/
|
||||
├── CloudronManifest.json # Package definition
|
||||
├── Dockerfile # Docker image build instructions
|
||||
├── start.sh # Initialization script
|
||||
├── nginx.conf # NGINX configuration
|
||||
├── supervisor.conf # Supervisor configuration for process management
|
||||
├── logo.png # App icon (128x128 PNG)
|
||||
├── casc_templates/ # Jenkins Configuration as Code templates
|
||||
│ ├── default.yaml # Default authentication config
|
||||
│ ├── ldap.yaml # LDAP authentication config
|
||||
│ └── oauth.yaml # OAuth/OIDC authentication config
|
||||
```
|
||||
|
||||
## Building the Package
|
||||
|
||||
1. Create a directory for your package and place all files in the appropriate structure.
|
||||
|
||||
2. Download a Jenkins logo (128x128 PNG) and save it as `logo.png`
|
||||
|
||||
3. Build the Docker image:
|
||||
```bash
|
||||
cloudron build
|
||||
```
|
||||
|
||||
4. Test the package locally:
|
||||
```bash
|
||||
cloudron install —image cloudron/jenkins
|
||||
```
|
||||
|
||||
## Authentication Configuration
|
||||
|
||||
The package supports three authentication methods:
|
||||
|
||||
1. **Default (Local)**: Uses Jenkins’ built-in user database
|
||||
2. **LDAP**: Uses Cloudron’s LDAP server for authentication
|
||||
3. **OAuth/OIDC**: Uses Cloudron’s OAuth service for single sign-on
|
||||
|
||||
The authentication method is automatically configured based on the presence of environment variables provided by Cloudron.
|
||||
|
||||
## Testing
|
||||
|
||||
After installation, test the following:
|
||||
|
||||
1. **Basic functionality**:
|
||||
- Access Jenkins through your Cloudron dashboard
|
||||
- Verify the initial admin password works
|
||||
- Create a simple pipeline job
|
||||
|
||||
2. **Authentication**:
|
||||
- Test LDAP integration by enabling the LDAP addon
|
||||
- Test OAuth/OIDC integration by enabling the OAuth addon
|
||||
- Verify user permissions are correctly applied
|
||||
|
||||
3. **Persistence**:
|
||||
- Install plugins through the Jenkins UI
|
||||
- Restart the app to verify plugins persist
|
||||
- Check that job configurations are maintained
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
- **Jenkins doesn’t start**: Check logs using `cloudron logs -f`
|
||||
- **Authentication issues**: Verify the correct addons are enabled and configuration is applied
|
||||
- **Permission problems**: Check the ownership and permissions of files in `/app/data`
|
||||
|
||||
## Updating Jenkins
|
||||
|
||||
When a new version of Jenkins is released, update the Dockerfile to pull the latest version and rebuild the package.
|
||||
|
||||
## Additional Notes
|
||||
|
||||
- The package uses Jenkins Configuration as Code (JCasC) to automate the setup process
|
||||
- Jenkins runs as the `cloudron` user for proper permissions
|
||||
- Files in `/app/data/jenkins_home` are persisted across restarts and updates
|
||||
- Initial admin password is set to ‘adminpass’ for local authentication
|
||||
|
||||
## Deployment to Cloudron App Store
|
||||
|
||||
If you wish to publish your app to the Cloudron App Store:
|
||||
|
||||
1. Update the CloudronManifest.json with your details
|
||||
2. Test thoroughly on your own Cloudron instance
|
||||
3. Follow the Cloudron App Publishing guidelines
|
||||
|
||||
Happy CI/CD with Jenkins on Cloudron!
|
@@ -0,0 +1,26 @@
|
||||
jenkins:
|
||||
systemMessage: "Jenkins configured with local authentication"
|
||||
securityRealm:
|
||||
local:
|
||||
allowsSignup: false
|
||||
enableCaptcha: false
|
||||
users:
|
||||
- id: "admin"
|
||||
password: "adminpass"
|
||||
|
||||
authorizationStrategy:
|
||||
globalMatrix:
|
||||
permissions:
|
||||
- "Overall/Administer:admin"
|
||||
- "Overall/Read:authenticated"
|
||||
- "Job/Read:authenticated"
|
||||
- "Job/Build:authenticated"
|
||||
- "Job/Create:authenticated"
|
||||
- "Job/Configure:authenticated"
|
||||
- "View/Read:authenticated"
|
||||
- "View/Create:authenticated"
|
||||
- "View/Configure:authenticated"
|
||||
|
||||
unclassified:
|
||||
location:
|
||||
url: "${JENKINS_URL}"
|
@@ -0,0 +1,32 @@
|
||||
jenkins:
|
||||
systemMessage: "Jenkins configured with Cloudron LDAP authentication"
|
||||
securityRealm:
|
||||
ldap:
|
||||
configurations:
|
||||
- server: "${CLOUDRON_LDAP_SERVER}"
|
||||
rootDN: "${CLOUDRON_LDAP_USERS_BASE_DN}"
|
||||
managerDN: "${CLOUDRON_LDAP_BIND_DN}"
|
||||
managerPasswordSecret: "${CLOUDRON_LDAP_BIND_PASSWORD}"
|
||||
userSearchBase: ""
|
||||
userSearch: "uid={0}"
|
||||
groupSearchBase: "${CLOUDRON_LDAP_GROUPS_BASE_DN}"
|
||||
groupSearchFilter: "memberUid={0}"
|
||||
displayNameAttributeName: "displayName"
|
||||
mailAddressAttributeName: "mail"
|
||||
|
||||
authorizationStrategy:
|
||||
globalMatrix:
|
||||
permissions:
|
||||
- "Overall/Administer:admin"
|
||||
- "Overall/Read:authenticated"
|
||||
- "Job/Read:authenticated"
|
||||
- "Job/Build:authenticated"
|
||||
- "Job/Create:authenticated"
|
||||
- "Job/Configure:authenticated"
|
||||
- "View/Read:authenticated"
|
||||
- "View/Create:authenticated"
|
||||
- "View/Configure:authenticated"
|
||||
|
||||
unclassified:
|
||||
location:
|
||||
url: "${JENKINS_URL}"
|
@@ -0,0 +1,35 @@
|
||||
jenkins:
|
||||
systemMessage: "Jenkins configured with Cloudron OpenID Connect authentication"
|
||||
securityRealm:
|
||||
oic:
|
||||
clientId: "${CLOUDRON_OAUTH_CLIENT_ID}"
|
||||
clientSecret: "${CLOUDRON_OAUTH_CLIENT_SECRET}"
|
||||
wellKnownOpenIDConfigurationUrl: "${CLOUDRON_OAUTH_ORIGIN}/.well-known/openid-configuration"
|
||||
userNameField: "preferred_username"
|
||||
tokenAuthMethod: "client_secret_basic"
|
||||
scopes: "openid email profile groups"
|
||||
fullNameFieldName: "name"
|
||||
emailFieldName: "email"
|
||||
groupsFieldName: "groups"
|
||||
pkceEnabled: true
|
||||
escapeHatchEnabled: true
|
||||
escapeHatchUsername: "admin"
|
||||
escapeHatchSecret: "adminpass"
|
||||
escapeHatchGroup: "admin"
|
||||
|
||||
authorizationStrategy:
|
||||
globalMatrix:
|
||||
permissions:
|
||||
- "Overall/Administer:admin"
|
||||
- "Overall/Read:authenticated"
|
||||
- "Job/Read:authenticated"
|
||||
- "Job/Build:authenticated"
|
||||
- "Job/Create:authenticated"
|
||||
- "Job/Configure:authenticated"
|
||||
- "View/Read:authenticated"
|
||||
- "View/Create:authenticated"
|
||||
- "View/Configure:authenticated"
|
||||
|
||||
unclassified:
|
||||
location:
|
||||
url: "${JENKINS_URL}"
|
55
Cloudron/WorkInProgress/jenkins.knownelement.com/nginx.conf
Normal file
55
Cloudron/WorkInProgress/jenkins.knownelement.com/nginx.conf
Normal file
@@ -0,0 +1,55 @@
|
||||
worker_processes 1;
|
||||
error_log stderr;
|
||||
pid /run/nginx.pid;
|
||||
daemon off;
|
||||
|
||||
events {
|
||||
worker_connections 768;
|
||||
}
|
||||
|
||||
http {
|
||||
sendfile on;
|
||||
tcp_nopush on;
|
||||
tcp_nodelay on;
|
||||
keepalive_timeout 65;
|
||||
types_hash_max_size 2048;
|
||||
include /etc/nginx/mime.types;
|
||||
default_type application/octet-stream;
|
||||
|
||||
# Disable access logs to stdout - Cloudron handles these
|
||||
access_log off;
|
||||
|
||||
server {
|
||||
listen 8000;
|
||||
|
||||
client_max_body_size 50M;
|
||||
|
||||
location / {
|
||||
proxy_pass http://127.0.0.1:8080;
|
||||
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;
|
||||
|
||||
# Required for Jenkins websocket connections
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "upgrade";
|
||||
|
||||
proxy_read_timeout 90;
|
||||
proxy_redirect http://127.0.0.1:8080 $scheme://$host;
|
||||
|
||||
# Fix potential security issues
|
||||
proxy_cookie_path / "/; HTTPOnly; Secure";
|
||||
}
|
||||
|
||||
# Special config for OIDC callback
|
||||
location /securityRealm/finishLogin {
|
||||
proxy_pass http://127.0.0.1:8080;
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
50
Cloudron/WorkInProgress/jenkins.knownelement.com/start.sh
Normal file
50
Cloudron/WorkInProgress/jenkins.knownelement.com/start.sh
Normal file
@@ -0,0 +1,50 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
# Jenkins home directory
|
||||
JENKINS_HOME=/app/data/jenkins_home
|
||||
|
||||
# Create necessary directories if they don't exist
|
||||
if [[ ! -d "${JENKINS_HOME}" ]]; then
|
||||
echo "Initializing Jenkins home directory"
|
||||
mkdir -p "${JENKINS_HOME}"
|
||||
cp -r /tmp/data/jenkins_home/* "${JENKINS_HOME}/" || true
|
||||
# Copy plugins
|
||||
mkdir -p "${JENKINS_HOME}/plugins"
|
||||
cp -r /tmp/data/plugins/* "${JENKINS_HOME}/plugins/" || true
|
||||
# Create directory for JCasC
|
||||
mkdir -p "${JENKINS_HOME}/casc_configs"
|
||||
fi
|
||||
|
||||
# Apply proper permissions
|
||||
chown -R cloudron:cloudron "${JENKINS_HOME}"
|
||||
|
||||
# Set up Jenkins environment variables
|
||||
export JENKINS_HOME
|
||||
export JENKINS_OPTS="--httpPort=8080"
|
||||
|
||||
# Disable setup wizard
|
||||
export JAVA_OPTS="-Djenkins.install.runSetupWizard=false"
|
||||
|
||||
# Setup JCasC configuration based on environment
|
||||
if [[ -n "${CLOUDRON_OAUTH_CLIENT_ID}" ]]; then
|
||||
echo "Setting up OAuth authentication"
|
||||
envsubst < /tmp/data/casc_configs/oauth.yaml > "${JENKINS_HOME}/casc_configs/oauth.yaml"
|
||||
export CASC_JENKINS_CONFIG="${JENKINS_HOME}/casc_configs/oauth.yaml"
|
||||
elif [[ -n "${CLOUDRON_LDAP_SERVER}" ]]; then
|
||||
echo "Setting up LDAP authentication"
|
||||
envsubst < /tmp/data/casc_configs/ldap.yaml > "${JENKINS_HOME}/casc_configs/ldap.yaml"
|
||||
export CASC_JENKINS_CONFIG="${JENKINS_HOME}/casc_configs/ldap.yaml"
|
||||
else
|
||||
echo "Using default authentication"
|
||||
envsubst < /tmp/data/casc_configs/default.yaml > "${JENKINS_HOME}/casc_configs/default.yaml"
|
||||
export CASC_JENKINS_CONFIG="${JENKINS_HOME}/casc_configs/default.yaml"
|
||||
fi
|
||||
|
||||
# Configure Jenkins URL
|
||||
JENKINS_URL="${CLOUDRON_APP_ORIGIN}"
|
||||
echo "Setting Jenkins URL to ${JENKINS_URL}"
|
||||
export JENKINS_URL
|
||||
|
||||
# Start supervisord, which will start NGINX and Jenkins
|
||||
exec /usr/bin/supervisord --nodaemon -c /etc/supervisor/supervisord.conf
|
@@ -0,0 +1,18 @@
|
||||
[program:nginx]
|
||||
command=nginx -c /app/code/nginx.conf
|
||||
stdout_logfile=/dev/stdout
|
||||
stdout_logfile_maxbytes=0
|
||||
stderr_logfile=/dev/stderr
|
||||
stderr_logfile_maxbytes=0
|
||||
autorestart=true
|
||||
|
||||
[program:jenkins]
|
||||
command=java -Djava.awt.headless=true -Djenkins.model.Jenkins.slaveAgentPort=50000 -Dhudson.model.UsageStatistics.disabled=true %(ENV_JAVA_OPTS)s -jar /usr/share/java/jenkins.war --httpPort=8080 --webroot=/var/cache/jenkins/war %(ENV_JENKINS_OPTS)s
|
||||
directory=/app/data/jenkins_home
|
||||
user=cloudron
|
||||
environment=HOME="/app/data/jenkins_home",USER="cloudron"
|
||||
stdout_logfile=/dev/stdout
|
||||
stdout_logfile_maxbytes=0
|
||||
stderr_logfile=/dev/stderr
|
||||
stderr_logfile_maxbytes=0
|
||||
autorestart=true
|
@@ -0,0 +1,52 @@
|
||||
{
|
||||
"id": "org.librenms.cloudronapp",
|
||||
"title": "LibreNMS",
|
||||
"author": "LibreNMS Team",
|
||||
"description": "LibreNMS is a fully featured network monitoring system that provides a wealth of features and device support.",
|
||||
"version": "24.4.0",
|
||||
"tagline": "Open Source Network Monitoring",
|
||||
"healthCheckPath": "/login",
|
||||
"httpPort": 8000,
|
||||
"addons": {
|
||||
"localstorage": {},
|
||||
"mysql": {
|
||||
"memoryLimit": 134217728
|
||||
},
|
||||
"redis": {}
|
||||
},
|
||||
"manifestVersion": 2,
|
||||
"website": "https://www.librenms.org/",
|
||||
"documentation": "https://docs.librenms.org/",
|
||||
"icon": "file://logo.png",
|
||||
"memoryLimit": 734003200,
|
||||
"minBoxVersion": "7.0.0",
|
||||
"tags": [
|
||||
"monitoring",
|
||||
"network",
|
||||
"snmp",
|
||||
"graphs",
|
||||
"alerts"
|
||||
],
|
||||
"postInstallMessage": "LibreNMS has been installed successfully!\n\nDefault login:\nUsername: admin\nPassword: admin\n\nPlease change your password after the first login.",
|
||||
"forceSSL": true,
|
||||
"installationProgress": true,
|
||||
"tcpPorts": {
|
||||
"SNMP": {
|
||||
"port": 161,
|
||||
"description": "SNMP port for device monitoring"
|
||||
}
|
||||
},
|
||||
"optionalSso": true,
|
||||
"sso": [
|
||||
{
|
||||
"name": "oidc",
|
||||
"configurePath": "/auth/oidc/login",
|
||||
"logoutPath": "/logout"
|
||||
},
|
||||
{
|
||||
"name": "ldap",
|
||||
"configurePath": "/auth/ldap/login",
|
||||
"logoutPath": "/logout"
|
||||
}
|
||||
]
|
||||
}
|
77
Cloudron/WorkInProgress/netmon.knownelement.com/Dockerfile
Normal file
77
Cloudron/WorkInProgress/netmon.knownelement.com/Dockerfile
Normal file
@@ -0,0 +1,77 @@
|
||||
FROM cloudron/base:4.2.0
|
||||
|
||||
# Install required packages
|
||||
RUN apt-get update && apt-get install -y \
|
||||
acl \
|
||||
composer \
|
||||
fping \
|
||||
git \
|
||||
graphviz \
|
||||
imagemagick \
|
||||
mariadb-client \
|
||||
mtr-tiny \
|
||||
nginx \
|
||||
nmap \
|
||||
php8.2-cli \
|
||||
php8.2-curl \
|
||||
php8.2-fpm \
|
||||
php8.2-gd \
|
||||
php8.2-gmp \
|
||||
php8.2-mbstring \
|
||||
php8.2-mysql \
|
||||
php8.2-snmp \
|
||||
php8.2-xml \
|
||||
php8.2-zip \
|
||||
python3 \
|
||||
python3-pip \
|
||||
python3-pymysql \
|
||||
python3-redis \
|
||||
python3-dotenv \
|
||||
python3-systemd \
|
||||
rrdtool \
|
||||
snmp \
|
||||
snmp-mibs-downloader \
|
||||
unzip \
|
||||
whois \
|
||||
supervisor \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Download MIBs
|
||||
RUN download-mibs
|
||||
|
||||
# Clone LibreNMS repository
|
||||
WORKDIR /app/code
|
||||
RUN git clone --depth 1 https://github.com/librenms/librenms.git .
|
||||
|
||||
# Install PHP dependencies
|
||||
RUN composer install --no-dev --no-interaction
|
||||
|
||||
# Install Python dependencies
|
||||
RUN pip3 install -r requirements.txt
|
||||
|
||||
# Create initial data directory structure
|
||||
RUN mkdir -p /tmp/data/rrd \
|
||||
/tmp/data/logs \
|
||||
/tmp/data/config \
|
||||
/tmp/data/plugins \
|
||||
/app/data/rrd \
|
||||
/app/data/logs \
|
||||
/app/data/config \
|
||||
/app/data/plugins
|
||||
|
||||
# Copy configuration files
|
||||
COPY nginx.conf /etc/nginx/sites-available/librenms
|
||||
RUN ln -sf /etc/nginx/sites-available/librenms /etc/nginx/sites-enabled/default
|
||||
COPY supervisord.conf /etc/supervisor/conf.d/librenms.conf
|
||||
COPY start.sh /app/code/
|
||||
COPY config.php /tmp/data/config/
|
||||
|
||||
# Set permissions
|
||||
RUN chmod +x /app/code/start.sh \
|
||||
&& chown -R cloudron:cloudron /app/code \
|
||||
&& chown -R cloudron:cloudron /tmp/data \
|
||||
&& chown -R cloudron:cloudron /app/data
|
||||
|
||||
WORKDIR /app/code
|
||||
|
||||
CMD ["/app/code/start.sh"]
|
@@ -0,0 +1,158 @@
|
||||
# LibreNMS for Cloudron - Build Notes
|
||||
|
||||
This document provides instructions for building, testing, and deploying the LibreNMS package to your Cloudron instance.
|
||||
|
||||
## Package Contents
|
||||
|
||||
The LibreNMS Cloudron package includes:
|
||||
|
||||
- **CloudronManifest.json**: The main configuration file for the Cloudron application
|
||||
- **Dockerfile**: Sets up the container with all required dependencies
|
||||
- **start.sh**: The entry point script that initializes and configures LibreNMS
|
||||
- **nginx.conf**: Web server configuration for LibreNMS
|
||||
- **supervisord.conf**: Process management for multiple services
|
||||
- **config.php**: Default LibreNMS configuration
|
||||
|
||||
## Building the Package
|
||||
|
||||
1. Create a new directory for the package:
|
||||
```bash
|
||||
mkdir librenms-cloudron
|
||||
cd librenms-cloudron
|
||||
```
|
||||
|
||||
2. Copy all files into this directory:
|
||||
- CloudronManifest.json
|
||||
- Dockerfile
|
||||
- start.sh
|
||||
- nginx.conf
|
||||
- supervisord.conf
|
||||
- config.php
|
||||
|
||||
3. Download the LibreNMS logo:
|
||||
```bash
|
||||
curl -o logo.png https://raw.githubusercontent.com/librenms/librenms/master/html/images/librenms_logo_light.svg
|
||||
```
|
||||
|
||||
4. Ensure proper file permissions:
|
||||
```bash
|
||||
chmod +x start.sh
|
||||
```
|
||||
|
||||
5. Build the Cloudron package:
|
||||
```bash
|
||||
cloudron build
|
||||
```
|
||||
|
||||
## Testing the Package
|
||||
|
||||
1. Install the app on your Cloudron for testing:
|
||||
```bash
|
||||
cloudron install —app librenms
|
||||
```
|
||||
|
||||
2. Access the LibreNMS web interface at the URL provided by Cloudron.
|
||||
|
||||
3. Log in with the default credentials:
|
||||
- Username: `admin`
|
||||
- Password: `admin`
|
||||
|
||||
4. Verify functionality by:
|
||||
- Adding a test device
|
||||
- Checking discovery and polling
|
||||
- Configuring alerts
|
||||
- Testing authentication (especially if using Cloudron SSO)
|
||||
|
||||
## Deploying to Production
|
||||
|
||||
1. Update the CloudronManifest.json with appropriate values:
|
||||
- Update `version` if needed
|
||||
- Adjust `memoryLimit` based on your production needs
|
||||
- Update `contactEmail` with your support email
|
||||
|
||||
2. Rebuild the package:
|
||||
```bash
|
||||
cloudron build
|
||||
```
|
||||
|
||||
3. Install on your production Cloudron:
|
||||
```bash
|
||||
cloudron install —app librenms
|
||||
```
|
||||
|
||||
## Authentication Configuration
|
||||
|
||||
### OIDC Authentication (Recommended)
|
||||
|
||||
The package automatically configures OIDC authentication when Cloudron SSO is enabled. This provides:
|
||||
|
||||
- Single sign-on with your Cloudron users
|
||||
- Automatic user provisioning
|
||||
- Group-based access control
|
||||
|
||||
### LDAP Authentication
|
||||
|
||||
If OIDC is not enabled, the package can use Cloudron’s LDAP server. This is configured automatically by the start.sh script.
|
||||
|
||||
### Manual Authentication
|
||||
|
||||
If neither OIDC nor LDAP is used, the package defaults to MySQL authentication with a local admin user.
|
||||
|
||||
## Data Persistence
|
||||
|
||||
The following data is stored in persistent volumes:
|
||||
|
||||
- **/app/data/rrd**: RRD files for graphing
|
||||
- **/app/data/logs**: LibreNMS logs
|
||||
- **/app/data/config**: Configuration files
|
||||
- **/app/data/plugins**: Custom plugins
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
If you encounter issues:
|
||||
|
||||
1. Check the logs:
|
||||
```bash
|
||||
cloudron logs -f librenms
|
||||
```
|
||||
|
||||
2. Verify database connection:
|
||||
```bash
|
||||
cloudron exec —app librenms — mysql -h “$CLOUDRON_MYSQL_HOST” -P “$CLOUDRON_MYSQL_PORT” -u “$CLOUDRON_MYSQL_USERNAME” -p”$CLOUDRON_MYSQL_PASSWORD” -e “SHOW TABLES” “$CLOUDRON_MYSQL_DATABASE”
|
||||
```
|
||||
|
||||
3. Check file permissions:
|
||||
```bash
|
||||
cloudron exec —app librenms — ls -la /app/data
|
||||
```
|
||||
|
||||
4. Restart the application:
|
||||
```bash
|
||||
cloudron restart —app librenms
|
||||
```
|
||||
|
||||
## Upgrading
|
||||
|
||||
To upgrade LibreNMS:
|
||||
|
||||
1. Update the git clone command in the Dockerfile to use the latest version tag
|
||||
2. Update the version in CloudronManifest.json
|
||||
3. Rebuild and upgrade the package:
|
||||
```bash
|
||||
cloudron build
|
||||
cloudron update —app librenms
|
||||
```
|
||||
|
||||
## Security Considerations
|
||||
|
||||
- The default admin password should be changed immediately after installation
|
||||
- Consider using Cloudron SSO to leverage your existing authentication system
|
||||
- SNMP port 161 is exposed for device monitoring - ensure proper network security
|
||||
|
||||
## Resource Usage
|
||||
|
||||
LibreNMS resource requirements depend on the number of monitored devices:
|
||||
|
||||
- For <100 devices: Default memory limit (734MB) should be sufficient
|
||||
- For 100-500 devices: Consider increasing memory limit to 1GB or more
|
||||
- For >500 devices: Consider distributed polling with multiple instances
|
88
Cloudron/WorkInProgress/netmon.knownelement.com/config.php
Normal file
88
Cloudron/WorkInProgress/netmon.knownelement.com/config.php
Normal file
@@ -0,0 +1,88 @@
|
||||
<?php
|
||||
|
||||
$config['db_host'] = getenv('DB_HOST');
|
||||
$config['db_port'] = getenv('DB_PORT');
|
||||
$config['db_user'] = getenv('DB_USER');
|
||||
$config['db_pass'] = getenv('DB_PASS');
|
||||
$config['db_name'] = getenv('DB_NAME');
|
||||
|
||||
// Redis settings (used for distributed polling)
|
||||
$config['redis']['host'] = getenv('REDIS_HOST');
|
||||
$config['redis']['port'] = getenv('REDIS_PORT');
|
||||
$config['redis']['db'] = getenv('REDIS_DB');
|
||||
$config['redis']['pass'] = getenv('REDIS_PASS');
|
||||
|
||||
// Base URL
|
||||
$config['base_url'] = getenv('APP_URL');
|
||||
|
||||
// Authentication mechanism - This will be modified by start.sh if needed
|
||||
$config['auth_mechanism'] = 'mysql';
|
||||
|
||||
// Enable alerting
|
||||
$config['alert']['enable'] = true;
|
||||
|
||||
// RRD storage
|
||||
$config['rrd_dir'] = '/app/data/rrd';
|
||||
|
||||
// Log directory
|
||||
$config['log_dir'] = '/app/data/logs';
|
||||
$config['log_file'] = '/app/data/logs/librenms.log';
|
||||
$config['auth_log'] = '/app/data/logs/auth.log';
|
||||
|
||||
// Plugin directory
|
||||
$config['plugin_dir'] = '/app/data/plugins';
|
||||
|
||||
// Default theme
|
||||
$config['webui']['default_theme'] = 'light';
|
||||
|
||||
// Path settings
|
||||
$config['fping'] = '/usr/bin/fping';
|
||||
$config['fping6'] = '/usr/bin/fping6';
|
||||
$config['snmpwalk'] = '/usr/bin/snmpwalk';
|
||||
$config['snmpget'] = '/usr/bin/snmpget';
|
||||
$config['snmpbulkwalk'] = '/usr/bin/snmpbulkwalk';
|
||||
$config['snmptranslate'] = '/usr/bin/snmptranslate';
|
||||
$config['rrdtool'] = '/usr/bin/rrdtool';
|
||||
$config['whois'] = '/usr/bin/whois';
|
||||
$config['ping'] = '/bin/ping';
|
||||
$config['mtr'] = '/usr/bin/mtr';
|
||||
$config['nmap'] = '/usr/bin/nmap';
|
||||
|
||||
// Disable in-app updates
|
||||
$config['update'] = 0;
|
||||
|
||||
// Security settings
|
||||
$config['allow_unauth_graphs'] = false;
|
||||
$config['allow_unauth_graphs_cidr'] = array();
|
||||
|
||||
// Alert tolerance window
|
||||
$config['alert']['tolerance_window'] = 5;
|
||||
|
||||
// Poller settings
|
||||
$config['poller_modules']['bgp'] = 1;
|
||||
$config['poller_modules']['ospf'] = 1;
|
||||
$config['poller_modules']['isis'] = 1;
|
||||
$config['poller_modules']['applications'] = 1;
|
||||
$config['poller_modules']['services'] = 1;
|
||||
|
||||
// Set timezone according to Cloudron environment
|
||||
$config['timezone'] = 'UTC';
|
||||
|
||||
// Auto-discovery settings
|
||||
$config['autodiscovery']['xdp'] = true;
|
||||
$config['autodiscovery']['ospf'] = true;
|
||||
$config['autodiscovery']['bgp'] = true;
|
||||
$config['autodiscovery']['snmpscan'] = true;
|
||||
|
||||
// API Settings
|
||||
$config['api']['cors']['enabled'] = false;
|
||||
$config['api']['cors']['origin'] = null;
|
||||
|
||||
// Rate Limiting
|
||||
$config['ratelimit']['enabled'] = true;
|
||||
$config['ratelimit']['api']['limit'] = 300;
|
||||
$config['ratelimit']['api']['period'] = 60;
|
||||
|
||||
// Default alert rules
|
||||
$config['enable_inventory'] = 1;
|
||||
$config['enable_syslog'] = 0;
|
39
Cloudron/WorkInProgress/netmon.knownelement.com/nginx.conf
Normal file
39
Cloudron/WorkInProgress/netmon.knownelement.com/nginx.conf
Normal file
@@ -0,0 +1,39 @@
|
||||
server {
|
||||
listen 8000;
|
||||
|
||||
server_name _;
|
||||
root /app/code/html;
|
||||
index index.php;
|
||||
|
||||
charset utf-8;
|
||||
gzip on;
|
||||
gzip_types text/css application/javascript text/javascript application/x-javascript image/svg+xml text/plain text/xsd text/xsl text/xml image/x-icon;
|
||||
|
||||
access_log /dev/stdout;
|
||||
error_log /dev/stderr;
|
||||
|
||||
# Set the client MAX Body size to allow for larger image uploads
|
||||
client_max_body_size 64M;
|
||||
|
||||
location / {
|
||||
try_files $uri $uri/ /index.php?$query_string;
|
||||
}
|
||||
|
||||
error_page 404 /index.php;
|
||||
|
||||
location ~ \.php$ {
|
||||
include fastcgi_params;
|
||||
fastcgi_split_path_info ^(.+\.php)(/.+)$;
|
||||
fastcgi_pass unix:/var/run/php/php8.2-fpm.sock;
|
||||
fastcgi_index index.php;
|
||||
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
||||
fastcgi_param REMOTE_ADDR $http_x_forwarded_for;
|
||||
fastcgi_param HTTP_X_FORWARDED_PROTO $http_x_forwarded_proto;
|
||||
fastcgi_param HTTPS on;
|
||||
fastcgi_read_timeout 900;
|
||||
}
|
||||
|
||||
location ~ /\.(?!well-known).* {
|
||||
deny all;
|
||||
}
|
||||
}
|
126
Cloudron/WorkInProgress/netmon.knownelement.com/start.sh
Normal file
126
Cloudron/WorkInProgress/netmon.knownelement.com/start.sh
Normal file
@@ -0,0 +1,126 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -eu
|
||||
|
||||
# Setup directories
|
||||
if [ ! -d "/app/data/rrd" ] || [ -z "$(ls -A /app/data/rrd)" ]; then
|
||||
echo "First run, initializing data directories..."
|
||||
mkdir -p /app/data/rrd
|
||||
mkdir -p /app/data/logs
|
||||
mkdir -p /app/data/config
|
||||
mkdir -p /app/data/plugins
|
||||
|
||||
# Copy initial configurations if they don't exist
|
||||
if [ ! -f "/app/data/config/config.php" ]; then
|
||||
cp /tmp/data/config/config.php /app/data/config/
|
||||
fi
|
||||
fi
|
||||
|
||||
# Create necessary log files
|
||||
touch /app/data/logs/librenms.log
|
||||
touch /app/data/logs/auth.log
|
||||
touch /app/data/logs/discovery.log
|
||||
touch /app/data/logs/poller.log
|
||||
|
||||
# Environment variables for database and redis
|
||||
export DB_HOST=${CLOUDRON_MYSQL_HOST}
|
||||
export DB_PORT=${CLOUDRON_MYSQL_PORT}
|
||||
export DB_USER=${CLOUDRON_MYSQL_USERNAME}
|
||||
export DB_PASS=${CLOUDRON_MYSQL_PASSWORD}
|
||||
export DB_NAME=${CLOUDRON_MYSQL_DATABASE}
|
||||
export REDIS_HOST=${CLOUDRON_REDIS_HOST}
|
||||
export REDIS_PORT=${CLOUDRON_REDIS_PORT}
|
||||
export REDIS_DB=0
|
||||
export REDIS_PASS=${CLOUDRON_REDIS_PASSWORD}
|
||||
export APP_URL=https://${CLOUDRON_APP_DOMAIN}
|
||||
|
||||
# Set up OIDC authentication if enabled
|
||||
if [[ -n "${CLOUDRON_OIDC_IDENTIFIER:-}" ]]; then
|
||||
echo "Configuring OIDC authentication..."
|
||||
sed -i "s|'auth_mechanism' => 'mysql'|'auth_mechanism' => 'socialite'|g" /app/data/config/config.php
|
||||
|
||||
# Add OIDC configuration
|
||||
cat >> /app/data/config/config.php << EOF
|
||||
\$config['auth_socialite_oidc']['enabled'] = true;
|
||||
\$config['auth_socialite_oidc']['client_id'] = '${CLOUDRON_OIDC_CLIENT_ID}';
|
||||
\$config['auth_socialite_oidc']['client_secret'] = '${CLOUDRON_OIDC_CLIENT_SECRET}';
|
||||
\$config['auth_socialite_oidc']['authorize_url'] = '${CLOUDRON_OIDC_ISSUER}/auth';
|
||||
\$config['auth_socialite_oidc']['token_url'] = '${CLOUDRON_OIDC_ISSUER}/token';
|
||||
\$config['auth_socialite_oidc']['userinfo_url'] = '${CLOUDRON_OIDC_ISSUER}/userinfo';
|
||||
\$config['auth_socialite_oidc']['scope'] = 'openid email profile groups';
|
||||
\$config['auth_socialite_oidc']['redirect'] = 'https://${CLOUDRON_APP_DOMAIN}/auth/oidc/callback';
|
||||
EOF
|
||||
fi
|
||||
|
||||
# Set up LDAP authentication if enabled and OIDC is not enabled
|
||||
if [[ -z "${CLOUDRON_OIDC_IDENTIFIER:-}" && -n "${CLOUDRON_LDAP_SERVER:-}" ]]; then
|
||||
echo "Configuring LDAP authentication..."
|
||||
sed -i "s|'auth_mechanism' => 'mysql'|'auth_mechanism' => 'ldap'|g" /app/data/config/config.php
|
||||
|
||||
# Add LDAP configuration
|
||||
cat >> /app/data/config/config.php << EOF
|
||||
\$config['auth_ldap_server'] = '${CLOUDRON_LDAP_SERVER}';
|
||||
\$config['auth_ldap_port'] = ${CLOUDRON_LDAP_PORT};
|
||||
\$config['auth_ldap_version'] = 3;
|
||||
\$config['auth_ldap_starttls'] = true;
|
||||
\$config['auth_ldap_prefix'] = '${CLOUDRON_LDAP_BIND_DN%%,*}';
|
||||
\$config['auth_ldap_suffix'] = ',${CLOUDRON_LDAP_BIND_DN#*,}';
|
||||
\$config['auth_ldap_group'] = '${CLOUDRON_LDAP_USERS_GROUP_DN}';
|
||||
\$config['auth_ldap_groupbase'] = '${CLOUDRON_LDAP_GROUPS_BASE_DN}';
|
||||
\$config['auth_ldap_groups']['admin']['level'] = 10;
|
||||
\$config['auth_ldap_groups']['admin']['group'] = '${CLOUDRON_LDAP_ADMINS_GROUP_DN}';
|
||||
EOF
|
||||
fi
|
||||
|
||||
# Fix permissions
|
||||
chown -R cloudron:cloudron /app/data
|
||||
|
||||
# Initialize database if needed
|
||||
echo "Checking database..."
|
||||
if ! mysql -h "${CLOUDRON_MYSQL_HOST}" -P "${CLOUDRON_MYSQL_PORT}" -u "${CLOUDRON_MYSQL_USERNAME}" -p"${CLOUDRON_MYSQL_PASSWORD}" -e "USE ${CLOUDRON_MYSQL_DATABASE}" 2>/dev/null; then
|
||||
echo "Setting up database schema..."
|
||||
cd /app/code
|
||||
php build-base.php
|
||||
fi
|
||||
|
||||
# Apply database updates if needed
|
||||
cd /app/code
|
||||
php includes/sql-schema/update.php
|
||||
|
||||
# Create admin user on first run if authentication is MySQL
|
||||
if [[ ! -n "${CLOUDRON_OIDC_IDENTIFIER:-}" && ! -n "${CLOUDRON_LDAP_SERVER:-}" ]]; then
|
||||
if ! mysql -h "${CLOUDRON_MYSQL_HOST}" -P "${CLOUDRON_MYSQL_PORT}" -u "${CLOUDRON_MYSQL_USERNAME}" -p"${CLOUDRON_MYSQL_PASSWORD}" -e "SELECT username FROM users WHERE username='admin'" ${CLOUDRON_MYSQL_DATABASE} 2>/dev/null | grep -q admin; then
|
||||
echo "Creating admin user..."
|
||||
php adduser.php admin admin 10 admin@localhost
|
||||
fi
|
||||
fi
|
||||
|
||||
# Link config file
|
||||
ln -sf /app/data/config/config.php /app/code/config.php
|
||||
|
||||
# Setup cron jobs
|
||||
echo "Setting up cron jobs..."
|
||||
cat > /etc/cron.d/librenms << EOF
|
||||
# Run a complete discovery of all devices once every 6 hours
|
||||
33 */6 * * * cloudron cd /app/code/ && php discovery.php -h all >> /app/data/logs/discovery-all.log 2>&1
|
||||
# Run a complete poll of all devices once every 5 minutes
|
||||
*/5 * * * * cloudron cd /app/code/ && php poller.php -h all >> /app/data/logs/poll-all.log 2>&1
|
||||
# Run hourly maintenance tasks
|
||||
15 * * * * cloudron cd /app/code/ && php daily.php >> /app/data/logs/daily.log 2>&1
|
||||
# Run daily maintenance tasks
|
||||
15 0 * * * cloudron cd /app/code/ && php daily.sh >> /app/data/logs/daily.log 2>&1
|
||||
# Check services
|
||||
*/5 * * * * cloudron cd /app/code/ && php check-services.php >> /app/data/logs/check-services.log 2>&1
|
||||
# Process alerts
|
||||
*/5 * * * * cloudron cd /app/code/ && php alerts.php >> /app/data/logs/alerts.log 2>&1
|
||||
# Poll billing
|
||||
*/5 * * * * cloudron cd /app/code/ && php poll-billing.php >> /app/data/logs/poll-billing.log 2>&1
|
||||
# Generate billing data
|
||||
01 * * * * cloudron cd /app/code/ && php billing-calculate.php >> /app/data/logs/billing-calculate.log 2>&1
|
||||
# Update device groups
|
||||
*/5 * * * * cloudron cd /app/code/ && php update-device-groups.php >> /app/data/logs/update-device-groups.log 2>&1
|
||||
EOF
|
||||
|
||||
# Start supervisord to manage all processes
|
||||
echo "Starting supervisord..."
|
||||
exec /usr/bin/supervisord -c /etc/supervisor/supervisord.conf
|
@@ -0,0 +1,41 @@
|
||||
[program:nginx]
|
||||
command=nginx -g "daemon off;"
|
||||
autostart=true
|
||||
autorestart=true
|
||||
priority=10
|
||||
stdout_logfile=/dev/stdout
|
||||
stdout_logfile_maxbytes=0
|
||||
stderr_logfile=/dev/stderr
|
||||
stderr_logfile_maxbytes=0
|
||||
|
||||
[program:php-fpm]
|
||||
command=/usr/sbin/php-fpm8.2 --nodaemonize
|
||||
autostart=true
|
||||
autorestart=true
|
||||
priority=5
|
||||
stdout_logfile=/dev/stdout
|
||||
stdout_logfile_maxbytes=0
|
||||
stderr_logfile=/dev/stderr
|
||||
stderr_logfile_maxbytes=0
|
||||
|
||||
[program:cron]
|
||||
command=cron -f
|
||||
autostart=true
|
||||
autorestart=true
|
||||
priority=15
|
||||
stdout_logfile=/dev/stdout
|
||||
stdout_logfile_maxbytes=0
|
||||
stderr_logfile=/dev/stderr
|
||||
stderr_logfile_maxbytes=0
|
||||
|
||||
[program:dispatcher-service]
|
||||
command=/usr/bin/python3 /app/code/dispatcher.py
|
||||
directory=/app/code
|
||||
user=cloudron
|
||||
autostart=true
|
||||
autorestart=true
|
||||
priority=20
|
||||
stdout_logfile=/dev/stdout
|
||||
stdout_logfile_maxbytes=0
|
||||
stderr_logfile=/dev/stderr
|
||||
stderr_logfile_maxbytes=0
|
@@ -0,0 +1,62 @@
|
||||
{
|
||||
"id": "com.resgrid.cloudron",
|
||||
"version": "1.0.0",
|
||||
"author": "Your Name <your.email@example.com>",
|
||||
"title": "Resgrid",
|
||||
"description": "Open Source Computer Aided Dispatch (CAD), Personnel, Shift Management, Automatic Vehicle Location (AVL) and Emergency Management Platform",
|
||||
"tagline": "Dispatch solution for first responders, business and industry",
|
||||
"website": "https://resgrid.com/",
|
||||
"contactEmail": "your.email@example.com",
|
||||
"icon": "/logo.png",
|
||||
"tags": [
|
||||
"dispatch",
|
||||
"emergency",
|
||||
"management",
|
||||
"first-responders"
|
||||
],
|
||||
"httpPort": 8000,
|
||||
"manifestVersion": 2,
|
||||
"healthCheckPath": "/",
|
||||
"memoryLimit": 1024,
|
||||
"documentationUrl": "https://resgrid-core.readthedocs.io/en/latest/",
|
||||
"addons": {
|
||||
"localstorage": {},
|
||||
"redis": {},
|
||||
"postgresql": {},
|
||||
"sendmail": {}
|
||||
},
|
||||
"tcpPorts": {
|
||||
"rabbitmq": {
|
||||
"title": "RabbitMQ",
|
||||
"description": "Port for RabbitMQ message queue service",
|
||||
"containerPort": 5672
|
||||
}
|
||||
},
|
||||
"postInstallMessage": "Resgrid has been successfully installed. The default administrator account is 'admin' with password 'changeme'. Please change this password immediately after the first login.",
|
||||
"minBoxVersion": "5.4.0",
|
||||
"forwardedPorts": [],
|
||||
"configurePath": "/settings",
|
||||
"env": {
|
||||
"RESGRID_CLOUDRON": "true",
|
||||
"RESGRID_DB_TYPE": "postgresql",
|
||||
"POSTGRES_HOST": "{{ postgresql.host }}",
|
||||
"POSTGRES_PORT": "{{ postgresql.port }}",
|
||||
"POSTGRES_USERNAME": "{{ postgresql.username }}",
|
||||
"POSTGRES_PASSWORD": "{{ postgresql.password }}",
|
||||
"POSTGRES_DATABASE": "{{ postgresql.database }}",
|
||||
"REDIS_HOST": "{{ redis.host }}",
|
||||
"REDIS_PORT": "{{ redis.port }}",
|
||||
"REDIS_PASSWORD": "{{ redis.password }}",
|
||||
"CLOUDRON_APP_DOMAIN": "{{ appDomain }}",
|
||||
"CLOUDRON_MAIL_SMTP_SERVER": "{{ mail.smtp.hostname }}",
|
||||
"CLOUDRON_MAIL_SMTP_PORT": "{{ mail.smtp.port }}",
|
||||
"CLOUDRON_MAIL_SMTP_USERNAME": "{{ mail.smtp.username }}",
|
||||
"CLOUDRON_MAIL_SMTP_PASSWORD": "{{ mail.smtp.password }}",
|
||||
"CLOUDRON_MAIL_FROM": "{{ mail.from }}",
|
||||
"CLOUDRON_OIDC_IDENTIFIER": "{{ oauth.clientId }}",
|
||||
"CLOUDRON_OIDC_CLIENT_ID": "{{ oauth.clientId }}",
|
||||
"CLOUDRON_OIDC_CLIENT_SECRET": "{{ oauth.clientSecret }}",
|
||||
"CLOUDRON_OIDC_ISSUER": "{{ oauth.issuer }}",
|
||||
"CLOUDRON_OIDC_ORIGIN": "{{ origin }}"
|
||||
}
|
||||
}
|
75
Cloudron/WorkInProgress/resgrid.knownelement.com/Dockerfile
Normal file
75
Cloudron/WorkInProgress/resgrid.knownelement.com/Dockerfile
Normal file
@@ -0,0 +1,75 @@
|
||||
FROM cloudron/base:4.2.0
|
||||
|
||||
# Environment variables
|
||||
ENV RESGRID_VERSION="0.5.30" \
|
||||
DEBIAN_FRONTEND="noninteractive" \
|
||||
DOTNET_RUNNING_IN_CONTAINER=true \
|
||||
DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=false \
|
||||
LC_ALL=en_US.UTF-8 \
|
||||
LANG=en_US.UTF-8
|
||||
|
||||
# Install dependencies
|
||||
RUN apt-get update && apt-get install -y \
|
||||
curl \
|
||||
wget \
|
||||
gnupg2 \
|
||||
apt-transport-https \
|
||||
software-properties-common \
|
||||
supervisor \
|
||||
nginx \
|
||||
vim \
|
||||
unzip \
|
||||
gettext-base \
|
||||
netcat-openbsd \
|
||||
locales \
|
||||
&& locale-gen en_US.UTF-8 \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Install .NET Core
|
||||
RUN curl -SL --output packages-microsoft-prod.deb https://packages.microsoft.com/config/debian/11/packages-microsoft-prod.deb \
|
||||
&& dpkg -i packages-microsoft-prod.deb \
|
||||
&& apt-get update \
|
||||
&& apt-get install -y dotnet-sdk-6.0 \
|
||||
&& rm -f packages-microsoft-prod.deb \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Download and extract Resgrid Docker setup files
|
||||
WORKDIR /tmp
|
||||
RUN wget -q https://github.com/Resgrid/Core/releases/download/v${RESGRID_VERSION}/resgrid.tgz \
|
||||
&& mkdir -p /tmp/resgrid \
|
||||
&& tar -xzf resgrid.tgz -C /tmp/resgrid \
|
||||
&& rm resgrid.tgz
|
||||
|
||||
# Create directory structure
|
||||
RUN mkdir -p /app/code \
|
||||
&& mkdir -p /app/data/config \
|
||||
&& mkdir -p /app/data/logs \
|
||||
&& mkdir -p /app/data/uploads \
|
||||
&& mkdir -p /app/data/backup
|
||||
|
||||
# Copy Resgrid components to the code directory
|
||||
WORKDIR /app/code
|
||||
|
||||
# Setup configuration directory for first run
|
||||
RUN mkdir -p /tmp/data/config
|
||||
|
||||
# Copy configuration files and setup scripts to temporary directory
|
||||
COPY start.sh /app/code/
|
||||
COPY nginx.conf /app/code/
|
||||
COPY supervisord.conf /app/code/
|
||||
COPY resgrid.env.template /app/code/
|
||||
|
||||
# Make start script executable
|
||||
RUN chmod +x /app/code/start.sh
|
||||
|
||||
# Ensure all files have the correct permissions
|
||||
RUN chown -R cloudron:cloudron /app
|
||||
|
||||
# Switch to the cloudron user
|
||||
USER cloudron
|
||||
|
||||
# Expose the port defined in CloudronManifest.json
|
||||
EXPOSE 8000
|
||||
|
||||
# Set the entrypoint to the start script
|
||||
ENTRYPOINT ["/app/code/start.sh"]
|
@@ -0,0 +1,137 @@
|
||||
# Resgrid Cloudron Package Build Notes
|
||||
|
||||
This document provides instructions for building, testing, and deploying the Resgrid Cloudron package.
|
||||
|
||||
## Package Overview
|
||||
|
||||
Resgrid is an open-source Computer Aided Dispatch (CAD), Personnel, Shift Management, Automatic Vehicle Location (AVL), and Emergency Management Platform. This Cloudron package installs Resgrid with the following components:
|
||||
|
||||
- Resgrid Web Core (user interface)
|
||||
- Resgrid Web Services (API backend)
|
||||
- Resgrid Workers Console (background processing)
|
||||
- Resgrid Events Service (real-time notifications using SignalR)
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Cloudron server (version 7.2.0 or higher)
|
||||
- Docker installed on your build machine
|
||||
- Git installed on your build machine
|
||||
- About 2GB+ of RAM available on your Cloudron server
|
||||
- MySQL, Redis, and RabbitMQ addons available on your Cloudron server
|
||||
|
||||
## Build Instructions
|
||||
|
||||
1. Clone the repository to your local machine:
|
||||
```bash
|
||||
git clone https://github.com/yourusername/cloudron-resgrid.git
|
||||
cd cloudron-resgrid
|
||||
```
|
||||
|
||||
2. Download the Resgrid logo and save it as `logo.png` in the package directory:
|
||||
```bash
|
||||
curl -o logo.png https://resgrid.com/images/logo.png
|
||||
```
|
||||
|
||||
3. Build the Cloudron package:
|
||||
```bash
|
||||
cloudron build
|
||||
```
|
||||
|
||||
4. If successful, the package file will be created in the current directory with a `.tar.gz` extension.
|
||||
|
||||
## Deployment Instructions
|
||||
|
||||
### Method 1: Direct Installation from Package
|
||||
|
||||
1. Install the package on your Cloudron server:
|
||||
```bash
|
||||
cloudron install —image resgrid.tar.gz
|
||||
```
|
||||
|
||||
2. Follow the on-screen instructions to complete the installation.
|
||||
|
||||
### Method 2: Using the Cloudron App Store (if published)
|
||||
|
||||
1. Log into your Cloudron dashboard
|
||||
2. Go to App Store
|
||||
3. Search for “Resgrid”
|
||||
4. Click “Install”
|
||||
5. Follow the on-screen instructions
|
||||
|
||||
## Post-Installation Configuration
|
||||
|
||||
After installation, you should:
|
||||
|
||||
1. Log in with the default admin credentials:
|
||||
- Username: admin@example.com
|
||||
- Password: (Auto-generated, check Cloudron post-install message)
|
||||
|
||||
2. Change the default admin password
|
||||
|
||||
3. Configure your department settings:
|
||||
- Set the department name
|
||||
- Configure time zone
|
||||
- Set up groups and roles
|
||||
|
||||
4. If using Cloudron SSO (recommended):
|
||||
- The app is already configured to use Cloudron’s OIDC provider
|
||||
- Users who log in via SSO will be created in Resgrid automatically
|
||||
- You’ll need to assign appropriate roles to these users in the Resgrid admin interface
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Database Connection Issues
|
||||
|
||||
If you encounter database connection issues:
|
||||
|
||||
1. Check the logs via the Cloudron dashboard
|
||||
2. Verify the MySQL addon is running
|
||||
3. Ensure the database credentials are correctly configured
|
||||
|
||||
### Redis or RabbitMQ Issues
|
||||
|
||||
1. Check the logs for connection errors
|
||||
2. Verify the addons are running
|
||||
3. Restart the app if necessary: `cloudron restart —app resgrid.yourdomain.com`
|
||||
|
||||
### Container Startup Problems
|
||||
|
||||
If one or more containers fail to start:
|
||||
|
||||
1. SSH into the app: `cloudron exec —app resgrid.yourdomain.com`
|
||||
2. Check Docker container status: `docker ps -a | grep resgrid`
|
||||
3. View container logs: `docker logs resgrid-web` (or replace with the problematic container name)
|
||||
|
||||
## Backup and Restore
|
||||
|
||||
The Cloudron platform automatically backs up all Resgrid data stored in:
|
||||
- MySQL database (via the MySQL addon)
|
||||
- Redis (via the Redis addon)
|
||||
- RabbitMQ (via the RabbitMQ addon)
|
||||
- Local files in `/app/data` (file uploads, configuration, etc.)
|
||||
|
||||
To manually create a backup:
|
||||
```bash
|
||||
cloudron backup create —app resgrid.yourdomain.com
|
||||
```
|
||||
|
||||
To restore from a backup:
|
||||
```bash
|
||||
cloudron restore —app resgrid.yourdomain.com —backup backup_id
|
||||
```
|
||||
|
||||
## Updating
|
||||
|
||||
When a new version of the Resgrid Cloudron package is available:
|
||||
|
||||
1. Download the new package version
|
||||
2. Update your existing installation:
|
||||
```bash
|
||||
cloudron update —app resgrid.yourdomain.com —image new-resgrid.tar.gz
|
||||
```
|
||||
|
||||
## Additional Resources
|
||||
|
||||
- [Resgrid Documentation](https://resgrid-core.readthedocs.io/)
|
||||
- [Cloudron Documentation](https://docs.cloudron.io/)
|
||||
- [Resgrid GitHub Repository](https://github.com/Resgrid/Core)
|
66
Cloudron/WorkInProgress/resgrid.knownelement.com/nginx.conf
Normal file
66
Cloudron/WorkInProgress/resgrid.knownelement.com/nginx.conf
Normal file
@@ -0,0 +1,66 @@
|
||||
server {
|
||||
listen 8000;
|
||||
server_name _;
|
||||
|
||||
access_log /dev/stdout;
|
||||
error_log /dev/stderr;
|
||||
|
||||
client_max_body_size 100M;
|
||||
|
||||
# Web application
|
||||
location / {
|
||||
proxy_pass http://localhost:8002;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "upgrade";
|
||||
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-Frame-Options SAMEORIGIN;
|
||||
proxy_read_timeout 90;
|
||||
}
|
||||
|
||||
# API endpoints
|
||||
location /api/ {
|
||||
proxy_pass http://localhost:8001/api/;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "upgrade";
|
||||
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_read_timeout 300;
|
||||
}
|
||||
|
||||
# Events/SignalR endpoint
|
||||
location /events/ {
|
||||
proxy_pass http://localhost:8003/;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "upgrade";
|
||||
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_read_timeout 300;
|
||||
}
|
||||
|
||||
# OIDC callback - required for Cloudron authentication
|
||||
location /api/v1/session/callback {
|
||||
proxy_pass http://localhost:8001/api/v1/session/callback;
|
||||
proxy_http_version 1.1;
|
||||
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;
|
||||
}
|
||||
|
||||
# Static files & uploads
|
||||
location /uploads/ {
|
||||
alias /app/data/uploads/;
|
||||
expires 30d;
|
||||
add_header Cache-Control "public, max-age=2592000";
|
||||
}
|
||||
}
|
@@ -0,0 +1,66 @@
|
||||
# Core Resgrid settings
|
||||
RESGRID__ApiUrl=${RESGRID_API_URL}
|
||||
RESGRID__BaseUrl=${RESGRID_BASE_URL}
|
||||
RESGRID__EventsUrl=${RESGRID_EVENTS_URL}
|
||||
RESGRID__PublicEventsUrl=${RESGRID_EVENTS_URL}
|
||||
RESGRID__AdminEmailAddress=admin@example.com
|
||||
RESGRID__AdminPassword=${RESGRID_ADMIN_PASSWORD}
|
||||
RESGRID__ApiKey=${RESGRID_API_KEY}
|
||||
|
||||
# Database connection
|
||||
RESGRID__DataConfig__Provider=sqlserver
|
||||
RESGRID__DataConfig__Server=${RESGRID_DB_HOST}
|
||||
RESGRID__DataConfig__Port=${RESGRID_DB_PORT}
|
||||
RESGRID__DataConfig__Database=${RESGRID_DB_NAME}
|
||||
RESGRID__DataConfig__UserName=${RESGRID_DB_USER}
|
||||
RESGRID__DataConfig__Password=${RESGRID_DB_PASSWORD}
|
||||
RESGRID__DataConfig__CommandTimeout=300
|
||||
RESGRID__DataConfig__ConnectionTimeout=30
|
||||
|
||||
# Redis connection
|
||||
RESGRID__Caching__RedisConnectionString=redis://:${RESGRID_REDIS_PASSWORD}@${RESGRID_REDIS_HOST}:${RESGRID_REDIS_PORT}
|
||||
RESGRID__Caching__Provider=redis
|
||||
|
||||
# RabbitMQ connection
|
||||
RESGRID__ServiceBusConfig__Provider=rabbitmq
|
||||
RESGRID__ServiceBusConfig__Server=${RESGRID_RABBITMQ_HOST}
|
||||
RESGRID__ServiceBusConfig__Port=${RESGRID_RABBITMQ_PORT}
|
||||
RESGRID__ServiceBusConfig__Username=${RESGRID_RABBITMQ_USER}
|
||||
RESGRID__ServiceBusConfig__Password=${RESGRID_RABBITMQ_PASSWORD}
|
||||
RESGRID__ServiceBusConfig__VirtualHost=${RESGRID_RABBITMQ_VHOST}
|
||||
|
||||
# Security settings
|
||||
RESGRID__Security__EnableSsl=true
|
||||
RESGRID__Security__RequireSSL=true
|
||||
RESGRID__Security__AllowLocalReg=false
|
||||
RESGRID__Security__DisableSignalR=false
|
||||
|
||||
# OIDC configuration
|
||||
RESGRID__Security__OIDC__Enabled=${RESGRID_OIDC_ENABLED}
|
||||
RESGRID__Security__OIDC__ClientId=${RESGRID_OIDC_CLIENT_ID}
|
||||
RESGRID__Security__OIDC__ClientSecret=${RESGRID_OIDC_CLIENT_SECRET}
|
||||
RESGRID__Security__OIDC__Authority=${RESGRID_OIDC_AUTHORITY}
|
||||
RESGRID__Security__OIDC__CallbackPath=${RESGRID_OIDC_CALLBACK_PATH}
|
||||
RESGRID__Security__OIDC__ResponseType=code
|
||||
RESGRID__Security__OIDC__GetClaimsFromUserInfoEndpoint=true
|
||||
RESGRID__Security__OIDC__RequireHttpsMetadata=true
|
||||
RESGRID__Security__OIDC__SaveTokens=true
|
||||
|
||||
# Email settings
|
||||
RESGRID__EmailConfig__Provider=smtp
|
||||
RESGRID__EmailConfig__Server=localhost
|
||||
RESGRID__EmailConfig__Port=25
|
||||
RESGRID__EmailConfig__FromEmail=no-reply@example.com
|
||||
RESGRID__EmailConfig__FromName=Resgrid System
|
||||
RESGRID__EmailConfig__Username=
|
||||
RESGRID__EmailConfig__Password=
|
||||
RESGRID__EmailConfig__EnableSsl=false
|
||||
|
||||
# File storage
|
||||
RESGRID__FileStorage__Provider=localstorage
|
||||
RESGRID__FileStorage__LocalStoragePath=/app/data/uploads
|
||||
|
||||
# Logging
|
||||
RESGRID__Logging__LogLevel=Information
|
||||
RESGRID__Logging__Provider=file
|
||||
RESGRID__Logging__FilePath=/app/data/logs
|
141
Cloudron/WorkInProgress/resgrid.knownelement.com/start.sh
Normal file
141
Cloudron/WorkInProgress/resgrid.knownelement.com/start.sh
Normal file
@@ -0,0 +1,141 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
# Function for logging
|
||||
log() {
|
||||
echo "$(date +"%Y-%m-%d %H:%M:%S"): $1"
|
||||
}
|
||||
|
||||
log "Starting Resgrid Cloudron App..."
|
||||
|
||||
# Initialize data directory if it's the first run
|
||||
if [ ! -f /app/data/config/.initialized ]; then
|
||||
log "First run detected, initializing data directory..."
|
||||
|
||||
# Copy initial configuration files if they don't exist
|
||||
if [ ! -f /app/data/config/resgrid.env ]; then
|
||||
log "Creating initial configuration..."
|
||||
|
||||
# Generate random keys and passwords
|
||||
ADMIN_PASSWORD=$(openssl rand -base64 12)
|
||||
DB_PASSWORD=${CLOUDRON_MYSQL_PASSWORD}
|
||||
API_KEY=$(openssl rand -hex 32)
|
||||
|
||||
# Create environment configuration from template
|
||||
export RESGRID_ADMIN_PASSWORD=$ADMIN_PASSWORD
|
||||
export RESGRID_DB_PASSWORD=$DB_PASSWORD
|
||||
export RESGRID_API_KEY=$API_KEY
|
||||
export RESGRID_DB_HOST=${CLOUDRON_MYSQL_HOST}
|
||||
export RESGRID_DB_PORT=${CLOUDRON_MYSQL_PORT}
|
||||
export RESGRID_DB_USER=${CLOUDRON_MYSQL_USERNAME}
|
||||
export RESGRID_DB_NAME=${CLOUDRON_MYSQL_DATABASE}
|
||||
export RESGRID_REDIS_HOST=${CLOUDRON_REDIS_HOST}
|
||||
export RESGRID_REDIS_PORT=${CLOUDRON_REDIS_PORT}
|
||||
export RESGRID_REDIS_PASSWORD=${CLOUDRON_REDIS_PASSWORD}
|
||||
export RESGRID_RABBITMQ_HOST=${CLOUDRON_RABBITMQ_HOST}
|
||||
export RESGRID_RABBITMQ_PORT=${CLOUDRON_RABBITMQ_PORT}
|
||||
export RESGRID_RABBITMQ_USER=${CLOUDRON_RABBITMQ_USERNAME}
|
||||
export RESGRID_RABBITMQ_PASSWORD=${CLOUDRON_RABBITMQ_PASSWORD}
|
||||
export RESGRID_RABBITMQ_VHOST=${CLOUDRON_RABBITMQ_VHOST}
|
||||
export RESGRID_BASE_URL="https://${CLOUDRON_APP_DOMAIN}"
|
||||
export RESGRID_API_URL="https://${CLOUDRON_APP_DOMAIN}/api"
|
||||
export RESGRID_EVENTS_URL="https://${CLOUDRON_APP_DOMAIN}/events"
|
||||
|
||||
# OIDC Configuration for Cloudron
|
||||
export RESGRID_OIDC_ENABLED="true"
|
||||
export RESGRID_OIDC_CLIENT_ID=${CLOUDRON_OIDC_CLIENT_ID}
|
||||
export RESGRID_OIDC_CLIENT_SECRET=${CLOUDRON_OIDC_CLIENT_SECRET}
|
||||
export RESGRID_OIDC_AUTHORITY=${CLOUDRON_OIDC_ISSUER}
|
||||
export RESGRID_OIDC_CALLBACK_PATH="/api/v1/session/callback"
|
||||
|
||||
# Process the template
|
||||
envsubst < /app/code/resgrid.env.template > /app/data/config/resgrid.env
|
||||
|
||||
log "Initial configuration created successfully."
|
||||
fi
|
||||
|
||||
# Mark as initialized
|
||||
touch /app/data/config/.initialized
|
||||
log "Initialization completed successfully."
|
||||
fi
|
||||
|
||||
# Link configuration files to expected locations
|
||||
ln -sf /app/data/config/resgrid.env /app/code/resgrid.env
|
||||
ln -sf /app/code/nginx.conf /etc/nginx/sites-available/default
|
||||
|
||||
# Ensure uploads directory exists with correct permissions
|
||||
mkdir -p /app/data/uploads
|
||||
chmod 755 /app/data/uploads
|
||||
|
||||
# Wait for database to be ready
|
||||
log "Waiting for MySQL database to be ready..."
|
||||
until nc -z ${CLOUDRON_MYSQL_HOST} ${CLOUDRON_MYSQL_PORT}; do
|
||||
log "MySQL is unavailable - sleeping for 5 seconds"
|
||||
sleep 5
|
||||
done
|
||||
log "MySQL is available, continuing..."
|
||||
|
||||
# Wait for Redis to be ready
|
||||
log "Waiting for Redis to be ready..."
|
||||
until nc -z ${CLOUDRON_REDIS_HOST} ${CLOUDRON_REDIS_PORT}; do
|
||||
log "Redis is unavailable - sleeping for 5 seconds"
|
||||
sleep 5
|
||||
done
|
||||
log "Redis is available, continuing..."
|
||||
|
||||
# Wait for RabbitMQ to be ready
|
||||
log "Waiting for RabbitMQ to be ready..."
|
||||
until nc -z ${CLOUDRON_RABBITMQ_HOST} ${CLOUDRON_RABBITMQ_PORT}; do
|
||||
log "RabbitMQ is unavailable - sleeping for 5 seconds"
|
||||
sleep 5
|
||||
done
|
||||
log "RabbitMQ is available, continuing..."
|
||||
|
||||
# Pull Resgrid Docker images
|
||||
log "Pulling Resgrid Docker images..."
|
||||
docker pull resgridllc/resgridwebcore:${RESGRID_VERSION}
|
||||
docker pull resgridllc/resgridwebservices:${RESGRID_VERSION}
|
||||
docker pull resgridllc/resgridworkersconsole:${RESGRID_VERSION}
|
||||
docker pull resgridllc/resgridwebevents:${RESGRID_VERSION}
|
||||
|
||||
# Create Docker network if it doesn't exist
|
||||
docker network create resgrid-network 2>/dev/null || true
|
||||
|
||||
# Run the containers with environment variables from the config file
|
||||
log "Starting Resgrid containers..."
|
||||
source /app/data/config/resgrid.env
|
||||
|
||||
# Start API Service
|
||||
docker run -d --name resgrid-api \
|
||||
--restart unless-stopped \
|
||||
--network resgrid-network \
|
||||
-p 8001:80 \
|
||||
--env-file /app/data/config/resgrid.env \
|
||||
resgridllc/resgridwebservices:${RESGRID_VERSION}
|
||||
|
||||
# Start Web Core
|
||||
docker run -d --name resgrid-web \
|
||||
--restart unless-stopped \
|
||||
--network resgrid-network \
|
||||
-p 8002:80 \
|
||||
--env-file /app/data/config/resgrid.env \
|
||||
resgridllc/resgridwebcore:${RESGRID_VERSION}
|
||||
|
||||
# Start Events Service
|
||||
docker run -d --name resgrid-events \
|
||||
--restart unless-stopped \
|
||||
--network resgrid-network \
|
||||
-p 8003:80 \
|
||||
--env-file /app/data/config/resgrid.env \
|
||||
resgridllc/resgridwebevents:${RESGRID_VERSION}
|
||||
|
||||
# Start Workers Console
|
||||
docker run -d --name resgrid-workers \
|
||||
--restart unless-stopped \
|
||||
--network resgrid-network \
|
||||
--env-file /app/data/config/resgrid.env \
|
||||
resgridllc/resgridworkersconsole:${RESGRID_VERSION}
|
||||
|
||||
# Start supervisord to manage Nginx and other processes
|
||||
log "Starting supervisord..."
|
||||
exec /usr/bin/supervisord -c /app/code/supervisord.conf
|
@@ -0,0 +1,24 @@
|
||||
[supervisord]
|
||||
nodaemon=true
|
||||
logfile=/dev/stdout
|
||||
logfile_maxbytes=0
|
||||
pidfile=/var/run/supervisord.pid
|
||||
user=root
|
||||
|
||||
[program:nginx]
|
||||
command=/usr/sbin/nginx -g "daemon off;"
|
||||
autostart=true
|
||||
autorestart=true
|
||||
stdout_logfile=/dev/stdout
|
||||
stdout_logfile_maxbytes=0
|
||||
stderr_logfile=/dev/stderr
|
||||
stderr_logfile_maxbytes=0
|
||||
|
||||
[program:docker-containers-monitor]
|
||||
command=/bin/bash -c "while true; do docker ps -a | grep -E 'resgrid-(api|web|events|workers)' | grep -v running > /dev/null && for c in resgrid-api resgrid-web resgrid-events resgrid-workers; do docker start $c 2>/dev/null || true; done; sleep 60; done"
|
||||
autostart=true
|
||||
autorestart=true
|
||||
stdout_logfile=/dev/stdout
|
||||
stdout_logfile_maxbytes=0
|
||||
stderr_logfile=/dev/stderr
|
||||
stderr_logfile_maxbytes=0
|
@@ -0,0 +1,43 @@
|
||||
{
|
||||
"id": "org.reviewboard.cloudron",
|
||||
"title": "ReviewBoard",
|
||||
"author": "Beanbag, Inc.",
|
||||
"description": "ReviewBoard is a web-based code review tool that helps projects and companies keep their code quality high and their bug count low.",
|
||||
"tagline": "A powerful web-based code review tool",
|
||||
"version": "1.0.0",
|
||||
"healthCheckPath": "/",
|
||||
"httpPort": 8000,
|
||||
"manifestVersion": 2,
|
||||
"website": "https://www.reviewboard.org",
|
||||
"documentationUrl": "https://www.reviewboard.org/docs/",
|
||||
"contactEmail": "support@cloudron.io",
|
||||
"icon": "file://logo.png",
|
||||
"tags": [
|
||||
"developer",
|
||||
"code-review",
|
||||
"collaboration"
|
||||
],
|
||||
"memoryLimit": 768,
|
||||
"addons": {
|
||||
"localstorage": {},
|
||||
"postgresql": {
|
||||
"version": "14"
|
||||
},
|
||||
"oidc": {
|
||||
"loginRedirectUri": "/api/v1/session/callback",
|
||||
"logoutRedirectUri": "/home",
|
||||
"tokenSignatureAlgorithm": "RS256"
|
||||
}
|
||||
},
|
||||
"minBoxVersion": "7.0.0",
|
||||
"postInstallMessage": "The initial admin account is created automatically using your Cloudron credentials. Please open the app to complete the setup process.",
|
||||
"installationProgress": {
|
||||
"message": "Installing ReviewBoard. This might take a few minutes...",
|
||||
"steps": [
|
||||
{ "id": "download", "title": "Downloading" },
|
||||
{ "id": "install", "title": "Installing Dependencies" },
|
||||
{ "id": "setup", "title": "Setting up ReviewBoard" },
|
||||
{ "id": "configure", "title": "Configuring for Cloudron" }
|
||||
]
|
||||
}
|
||||
}
|
@@ -0,0 +1,44 @@
|
||||
FROM cloudron/base:4.2.0
|
||||
|
||||
# Install required packages
|
||||
RUN apt-get update && \
|
||||
DEBIAN_FRONTEND=noninteractive apt-get install -y \
|
||||
python3 python3-pip python3-dev python3-venv \
|
||||
nginx supervisor \
|
||||
memcached libpq-dev \
|
||||
libldap2-dev libsasl2-dev \
|
||||
git-core subversion \
|
||||
libxml2-dev libxslt1-dev \
|
||||
libmagic-dev \
|
||||
gcc && \
|
||||
apt-get clean && \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Create Python virtual environment
|
||||
RUN python3 -m venv /app/code/venv
|
||||
ENV PATH="/app/code/venv/bin:${PATH}"
|
||||
|
||||
# Install Review Board dependencies
|
||||
RUN pip3 install --no-cache-dir --upgrade pip wheel setuptools && \
|
||||
pip3 install --no-cache-dir psycopg2-binary gunicorn django-storages
|
||||
|
||||
# Install Review Board
|
||||
RUN pip3 install --no-cache-dir reviewboard
|
||||
|
||||
# Install OIDC authentication
|
||||
RUN pip3 install --no-cache-dir mozilla-django-oidc
|
||||
|
||||
# Install LDAP authentication
|
||||
RUN pip3 install --no-cache-dir django-auth-ldap
|
||||
|
||||
# Make the data directories ready
|
||||
RUN mkdir -p /app/data/media /app/data/static /app/data/logs /app/data/conf /app/data/site
|
||||
|
||||
# Copy configuration files
|
||||
COPY nginx.conf /etc/nginx/sites-available/default
|
||||
COPY supervisord.conf /etc/supervisor/conf.d/supervisord.conf
|
||||
COPY start.sh /app/code/start.sh
|
||||
RUN chmod +x /app/code/start.sh
|
||||
|
||||
# Set up the entry point
|
||||
CMD ["/app/code/start.sh"]
|
@@ -0,0 +1,147 @@
|
||||
# Review Board - Cloudron Build Notes
|
||||
|
||||
This document provides instructions for building, testing, and deploying the Review Board Cloudron package.
|
||||
|
||||
## Package Overview
|
||||
|
||||
Review Board is a powerful web-based code review tool that helps teams review code, documents, and images before they are committed. This package configures Review Board to run on Cloudron with the following features:
|
||||
|
||||
- PostgreSQL database for data storage
|
||||
- Memcached for caching
|
||||
- Nginx as the web server
|
||||
- Gunicorn as the WSGI server
|
||||
- Support for Cloudron’s OIDC and LDAP authentication
|
||||
- Proper data separation following Cloudron’s filesystem layout
|
||||
|
||||
## Prerequisites
|
||||
|
||||
1. Cloudron CLI tool installed (`npm install -g cloudron`)
|
||||
2. Docker installed and running
|
||||
3. Cloudron account with administrative access
|
||||
|
||||
## Files Included in the Package
|
||||
|
||||
1. **CloudronManifest.json** - Defines the application for Cloudron
|
||||
2. **Dockerfile** - Instructions for building the Docker image
|
||||
3. **start.sh** - Initialization and startup script
|
||||
4. **supervisord.conf** - Process management configuration
|
||||
5. **nginx.conf** - Web server configuration
|
||||
|
||||
## Building the Package
|
||||
|
||||
1. Create a new directory for your package files:
|
||||
```bash
|
||||
mkdir reviewboard-cloudron
|
||||
cd reviewboard-cloudron
|
||||
```
|
||||
|
||||
2. Create all the package files in this directory.
|
||||
|
||||
3. Download the Review Board icon and save it as `icon.png`:
|
||||
```bash
|
||||
curl -L “https://raw.githubusercontent.com/reviewboard/reviewboard/master/reviewboard/static/rb/images/logo.png” -o icon.png
|
||||
```
|
||||
|
||||
4. Build the package:
|
||||
```bash
|
||||
cloudron build
|
||||
```
|
||||
|
||||
## Testing Locally (Optional)
|
||||
|
||||
1. Run the Docker image locally to test basic functionality:
|
||||
```bash
|
||||
docker run -p 8000:8000 cloudron/reviewboard-app:1.0.0
|
||||
```
|
||||
|
||||
2. Access the application at http://localhost:8000 to check if it starts correctly.
|
||||
|
||||
## Deploying to Cloudron
|
||||
|
||||
1. Install the package on your Cloudron:
|
||||
```bash
|
||||
cloudron install —image cloudron/reviewboard-app:1.0.0
|
||||
```
|
||||
|
||||
2. Or, to update an existing installation:
|
||||
```bash
|
||||
cloudron update —image cloudron/reviewboard-app:1.0.0 —app reviewboard.yourdomain.com
|
||||
```
|
||||
|
||||
## Post-Installation
|
||||
|
||||
1. Access your Review Board instance at the URL assigned by Cloudron.
|
||||
2. Log in using the initial admin credentials:
|
||||
- Username: `admin`
|
||||
- Password: Check the file `/app/data/admin_password.txt` inside the app container:
|
||||
```bash
|
||||
cloudron exec —app reviewboard.yourdomain.com cat /app/data/admin_password.txt
|
||||
```
|
||||
|
||||
3. Configure your repository connections in the Review Board admin interface at `/admin/`.
|
||||
|
||||
## Authentication Details
|
||||
|
||||
### OIDC Authentication (Default)
|
||||
|
||||
The package is configured to use Cloudron’s OIDC provider when available. Users logging in via OIDC will be automatically provisioned in Review Board.
|
||||
|
||||
### LDAP Authentication (Alternative)
|
||||
|
||||
If OIDC is not available, the package will fall back to using Cloudron’s LDAP server for authentication.
|
||||
|
||||
## Repository Support
|
||||
|
||||
Review Board supports the following repository types:
|
||||
- Git
|
||||
- SVN
|
||||
- Mercurial
|
||||
- Perforce
|
||||
- Bazaar
|
||||
- CVS
|
||||
- IBM Rational ClearCase
|
||||
- And more
|
||||
|
||||
Configure these in the Admin > Repositories section after login.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
1. Check application logs:
|
||||
```bash
|
||||
cloudron logs —app reviewboard.yourdomain.com
|
||||
```
|
||||
|
||||
2. Access the container directly to troubleshoot:
|
||||
```bash
|
||||
cloudron exec —app reviewboard.yourdomain.com bash
|
||||
```
|
||||
|
||||
3. Validate database connectivity:
|
||||
```bash
|
||||
cloudron exec —app reviewboard.yourdomain.com psql “$CLOUDRON_POSTGRESQL_URL”
|
||||
```
|
||||
|
||||
4. If Review Board shows errors about missing repositories, ensure they are accessible from the Cloudron container.
|
||||
|
||||
## Backup and Restore
|
||||
|
||||
Cloudron automatically backs up the `/app/data` directory, which includes:
|
||||
- Database (via PostgreSQL addon)
|
||||
- Media files (uploaded files, screenshots, etc.)
|
||||
- Configuration files
|
||||
- Repository cache
|
||||
|
||||
No additional backup configuration is necessary.
|
||||
|
||||
## Upgrading Review Board
|
||||
|
||||
When a new version of Review Board is released:
|
||||
|
||||
1. Update the Dockerfile to install the new version
|
||||
2. Rebuild the Docker image
|
||||
3. Update the Cloudron app using the `cloudron update` command
|
||||
|
||||
## Additional Resources
|
||||
|
||||
- [Review Board Documentation](https://www.reviewboard.org/docs/)
|
||||
- [Cloudron Documentation](https://docs.cloudron.io/)
|
@@ -0,0 +1,43 @@
|
||||
server {
|
||||
listen 8000;
|
||||
server_name CLOUDRON_APP_DOMAIN;
|
||||
|
||||
client_max_body_size 100M;
|
||||
|
||||
# Handle static and media files
|
||||
location /static/ {
|
||||
alias /app/data/static/;
|
||||
expires 30d;
|
||||
}
|
||||
|
||||
location /media/ {
|
||||
alias /app/data/media/;
|
||||
expires 30d;
|
||||
}
|
||||
|
||||
# Forward requests to the Django application
|
||||
location / {
|
||||
proxy_pass http://127.0.0.1:8001;
|
||||
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_connect_timeout 300s;
|
||||
proxy_read_timeout 300s;
|
||||
}
|
||||
|
||||
# Set up OIDC callback path
|
||||
location /api/v1/session/callback {
|
||||
proxy_pass http://127.0.0.1:8001;
|
||||
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;
|
||||
}
|
||||
|
||||
# Handle errors
|
||||
error_page 500 502 503 504 /50x.html;
|
||||
location = /50x.html {
|
||||
root /usr/share/nginx/html;
|
||||
}
|
||||
}
|
187
Cloudron/WorkInProgress/reviewboard.knownelement.com/start.sh
Normal file
187
Cloudron/WorkInProgress/reviewboard.knownelement.com/start.sh
Normal file
@@ -0,0 +1,187 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
# Create data directories if they don't exist
|
||||
if [ ! -f /app/data/.initialized ]; then
|
||||
echo "Initializing Review Board data directories..."
|
||||
|
||||
# Create directories
|
||||
mkdir -p /app/data/conf
|
||||
mkdir -p /app/data/media
|
||||
mkdir -p /app/data/static
|
||||
mkdir -p /app/data/logs
|
||||
|
||||
# Generate a random admin password and save it
|
||||
ADMIN_PASSWORD=$(< /dev/urandom tr -dc _A-Z-a-z-0-9 | head -c16)
|
||||
echo $ADMIN_PASSWORD > /app/data/admin_password.txt
|
||||
chmod 640 /app/data/admin_password.txt
|
||||
|
||||
# Mark as initialized
|
||||
touch /app/data/.initialized
|
||||
echo "Initialization complete."
|
||||
fi
|
||||
|
||||
# Set proper ownership
|
||||
chown -R cloudron:cloudron /app/data
|
||||
|
||||
# Configure database connection
|
||||
if [ ! -f /app/data/conf/settings_local.py ]; then
|
||||
echo "Creating Review Board configuration..."
|
||||
|
||||
# Get database connection details from CLOUDRON_POSTGRESQL_URL
|
||||
DB_HOST=$(echo "${CLOUDRON_POSTGRESQL_URL}" | cut -d@ -f2 | cut -d/ -f1)
|
||||
DB_NAME=$(echo "${CLOUDRON_POSTGRESQL_URL}" | cut -d/ -f4)
|
||||
DB_USER=$(echo "${CLOUDRON_POSTGRESQL_URL}" | cut -d/ -f3 | cut -d: -f1)
|
||||
DB_PASSWORD=$(echo "${CLOUDRON_POSTGRESQL_URL}" | cut -d: -f3 | cut -d@ -f1)
|
||||
|
||||
# Create settings_local.py
|
||||
cat > /app/data/conf/settings_local.py << EOF
|
||||
# Cloudron Review Board Settings
|
||||
import os
|
||||
|
||||
# Database settings
|
||||
DATABASES = {
|
||||
'default': {
|
||||
'ENGINE': 'django.db.backends.postgresql',
|
||||
'NAME': '${DB_NAME}',
|
||||
'USER': '${DB_USER}',
|
||||
'PASSWORD': '${DB_PASSWORD}',
|
||||
'HOST': '${DB_HOST}',
|
||||
}
|
||||
}
|
||||
|
||||
# Site settings
|
||||
SITE_ROOT = '/'
|
||||
MEDIA_ROOT = '/app/data/media'
|
||||
STATIC_ROOT = '/app/data/static'
|
||||
|
||||
# Email settings
|
||||
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
|
||||
EMAIL_HOST = 'mail'
|
||||
EMAIL_PORT = 25
|
||||
DEFAULT_FROM_EMAIL = 'reviewboard@${CLOUDRON_APP_DOMAIN}'
|
||||
SERVER_EMAIL = 'reviewboard@${CLOUDRON_APP_DOMAIN}'
|
||||
|
||||
# Cache settings
|
||||
CACHES = {
|
||||
'default': {
|
||||
'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
|
||||
'LOCATION': '127.0.0.1:11211',
|
||||
}
|
||||
}
|
||||
EOF
|
||||
|
||||
# Add authentication settings based on Cloudron's environment
|
||||
if [ -n "${CLOUDRON_LDAP_SERVER}" ]; then
|
||||
# LDAP Authentication
|
||||
cat >> /app/data/conf/settings_local.py << EOF
|
||||
# LDAP Authentication
|
||||
AUTHENTICATION_BACKENDS = (
|
||||
'django_auth_ldap.backend.LDAPBackend',
|
||||
'django.contrib.auth.backends.ModelBackend',
|
||||
)
|
||||
|
||||
import ldap
|
||||
from django_auth_ldap.config import LDAPSearch, GroupOfNamesType
|
||||
|
||||
AUTH_LDAP_SERVER_URI = "ldap://${CLOUDRON_LDAP_SERVER}:${CLOUDRON_LDAP_PORT}"
|
||||
AUTH_LDAP_BIND_DN = "${CLOUDRON_LDAP_BIND_DN}"
|
||||
AUTH_LDAP_BIND_PASSWORD = "${CLOUDRON_LDAP_BIND_PASSWORD}"
|
||||
AUTH_LDAP_USER_SEARCH = LDAPSearch(
|
||||
"${CLOUDRON_LDAP_USERS_BASE_DN}",
|
||||
ldap.SCOPE_SUBTREE,
|
||||
"(${CLOUDRON_LDAP_USERNAME_FIELD}=%(user)s)"
|
||||
)
|
||||
AUTH_LDAP_GROUP_SEARCH = LDAPSearch(
|
||||
"${CLOUDRON_LDAP_GROUPS_BASE_DN}",
|
||||
ldap.SCOPE_SUBTREE,
|
||||
"(objectClass=groupOfNames)"
|
||||
)
|
||||
AUTH_LDAP_GROUP_TYPE = GroupOfNamesType()
|
||||
AUTH_LDAP_USER_ATTR_MAP = {
|
||||
"first_name": "givenName",
|
||||
"last_name": "sn",
|
||||
"email": "mail"
|
||||
}
|
||||
AUTH_LDAP_ALWAYS_UPDATE_USER = True
|
||||
EOF
|
||||
elif [ -n "${CLOUDRON_OIDC_IDENTIFIER}" ]; then
|
||||
# OIDC Authentication
|
||||
cat >> /app/data/conf/settings_local.py << EOF
|
||||
# OIDC Authentication
|
||||
AUTHENTICATION_BACKENDS = (
|
||||
'mozilla_django_oidc.auth.OIDCAuthenticationBackend',
|
||||
'django.contrib.auth.backends.ModelBackend',
|
||||
)
|
||||
|
||||
OIDC_RP_CLIENT_ID = "${CLOUDRON_OIDC_CLIENT_ID}"
|
||||
OIDC_RP_CLIENT_SECRET = "${CLOUDRON_OIDC_CLIENT_SECRET}"
|
||||
OIDC_OP_AUTHORIZATION_ENDPOINT = "${CLOUDRON_OIDC_ENDPOINT}/authorize"
|
||||
OIDC_OP_TOKEN_ENDPOINT = "${CLOUDRON_OIDC_ENDPOINT}/token"
|
||||
OIDC_OP_USER_ENDPOINT = "${CLOUDRON_OIDC_ENDPOINT}/userinfo"
|
||||
OIDC_OP_JWKS_ENDPOINT = "${CLOUDRON_OIDC_ENDPOINT}/jwks"
|
||||
OIDC_AUTHENTICATE_CLASS = 'mozilla_django_oidc.views.OIDCAuthenticationRequestView'
|
||||
OIDC_CALLBACK_CLASS = 'mozilla_django_oidc.views.OIDCAuthenticationCallbackView'
|
||||
LOGIN_REDIRECT_URL = '/'
|
||||
LOGOUT_REDIRECT_URL = '/'
|
||||
|
||||
def oidc_username_transform(username):
|
||||
return username.split('@')[0]
|
||||
|
||||
OIDC_USERNAME_ALGO = oidc_username_transform
|
||||
EOF
|
||||
fi
|
||||
fi
|
||||
|
||||
# Initialize the Review Board site if not already done
|
||||
if [ ! -f /app/data/.db_initialized ]; then
|
||||
echo "Setting up the Review Board site..."
|
||||
|
||||
# Get database connection details
|
||||
DB_HOST=$(echo "${CLOUDRON_POSTGRESQL_URL}" | cut -d@ -f2 | cut -d/ -f1)
|
||||
DB_NAME=$(echo "${CLOUDRON_POSTGRESQL_URL}" | cut -d/ -f4)
|
||||
DB_USER=$(echo "${CLOUDRON_POSTGRESQL_URL}" | cut -d/ -f3 | cut -d: -f1)
|
||||
DB_PASSWORD=$(echo "${CLOUDRON_POSTGRESQL_URL}" | cut -d: -f3 | cut -d@ -f1)
|
||||
|
||||
# Create a site directory for Review Board
|
||||
rb-site install --noinput \
|
||||
--domain-name=${CLOUDRON_APP_DOMAIN} \
|
||||
--site-root=/ \
|
||||
--static-url=static/ \
|
||||
--media-url=media/ \
|
||||
--db-type=postgresql \
|
||||
--db-name=${DB_NAME} \
|
||||
--db-user=${DB_USER} \
|
||||
--db-pass=${DB_PASSWORD} \
|
||||
--db-host=${DB_HOST} \
|
||||
--cache-type=memcached \
|
||||
--cache-info=localhost:11211 \
|
||||
--web-server-type=wsgi \
|
||||
--admin-user=admin \
|
||||
--admin-password=$(cat /app/data/admin_password.txt) \
|
||||
--admin-email=admin@${CLOUDRON_APP_DOMAIN} \
|
||||
/app/data/site
|
||||
|
||||
# Copy settings_local.py to the site
|
||||
cp /app/data/conf/settings_local.py /app/data/site/conf/settings_local.py
|
||||
|
||||
# Mark as initialized
|
||||
touch /app/data/.db_initialized
|
||||
echo "Database initialization complete."
|
||||
fi
|
||||
|
||||
# Collect static files if they don't exist yet
|
||||
if [ ! -f /app/data/.static_collected ]; then
|
||||
echo "Collecting static files..."
|
||||
cd /app/data/site
|
||||
PYTHONPATH=/app/data/site python /app/data/site/manage.py collectstatic --noinput
|
||||
touch /app/data/.static_collected
|
||||
echo "Static files collected."
|
||||
fi
|
||||
|
||||
# Configure NGINX to use the static and media directories
|
||||
sed -i "s|CLOUDRON_APP_DOMAIN|${CLOUDRON_APP_DOMAIN}|g" /etc/nginx/sites-available/default
|
||||
|
||||
# Start services using supervisord
|
||||
echo "Starting Review Board..."
|
||||
exec /usr/bin/supervisord -c /etc/supervisor/supervisord.conf
|
@@ -0,0 +1,35 @@
|
||||
[supervisord]
|
||||
nodaemon=true
|
||||
logfile=/dev/stdout
|
||||
logfile_maxbytes=0
|
||||
user=root
|
||||
|
||||
[program:memcached]
|
||||
command=/usr/bin/memcached -m 64 -p 11211 -u nobody -l 127.0.0.1
|
||||
autostart=true
|
||||
autorestart=true
|
||||
stdout_logfile=/dev/stdout
|
||||
stdout_logfile_maxbytes=0
|
||||
stderr_logfile=/dev/stderr
|
||||
stderr_logfile_maxbytes=0
|
||||
|
||||
[program:reviewboard]
|
||||
command=/app/code/venv/bin/gunicorn --bind 127.0.0.1:8001 --workers 2 --timeout 90 wsgi:application
|
||||
directory=/app/data/site
|
||||
user=cloudron
|
||||
autostart=true
|
||||
autorestart=true
|
||||
stdout_logfile=/dev/stdout
|
||||
stdout_logfile_maxbytes=0
|
||||
stderr_logfile=/dev/stderr
|
||||
stderr_logfile_maxbytes=0
|
||||
environment=HOME="/app/data",PYTHONPATH="/app/data/site"
|
||||
|
||||
[program:nginx]
|
||||
command=/usr/sbin/nginx -g "daemon off;"
|
||||
autostart=true
|
||||
autorestart=true
|
||||
stdout_logfile=/dev/stdout
|
||||
stdout_logfile_maxbytes=0
|
||||
stderr_logfile=/dev/stderr
|
||||
stderr_logfile_maxbytes=0
|
@@ -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"
|
||||
}
|
||||
}
|
||||
}
|
65
Cloudron/WorkInProgress/rundeck.knownelement.com/Dockerfile
Normal file
65
Cloudron/WorkInProgress/rundeck.knownelement.com/Dockerfile
Normal file
@@ -0,0 +1,65 @@
|
||||
FROM cloudron/base:4.2.0
|
||||
|
||||
# Install dependencies
|
||||
RUN apt-get update && \
|
||||
apt-get install -y --no-install-recommends \
|
||||
openjdk-11-jre-headless \
|
||||
curl \
|
||||
supervisor \
|
||||
nginx \
|
||||
procps \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Set Environment Variables
|
||||
ENV RDECK_BASE=/app/data \
|
||||
RUNDECK_SERVER_DATASTORE_DRIVER="org.postgresql.Driver" \
|
||||
RUNDECK_GRAILS_URL="https://{{ cloudron_app_domain }}" \
|
||||
RUNDECK_SERVER_CONTEXTPATH="/" \
|
||||
RUNDECK_SERVER_FORWARDED=true \
|
||||
RUNDECK_LOGGING_STRATEGY=CONSOLE \
|
||||
SERVER_SERVLET_CONTEXT_PATH="/" \
|
||||
RUNDECK_JAASLOGIN=true \
|
||||
RUNDECK_SERVER_ADDRESS=127.0.0.1 \
|
||||
RUNDECK_SERVER_PORT=4440
|
||||
|
||||
# Create necessary directories
|
||||
RUN mkdir -p /app/code /app/data \
|
||||
/app/data/etc \
|
||||
/app/data/server/data \
|
||||
/app/data/var/logs \
|
||||
/app/data/projects \
|
||||
/app/data/libext \
|
||||
/app/data/.ssh \
|
||||
/tmp/data/etc \
|
||||
/tmp/data/server/data \
|
||||
/tmp/data/var/logs \
|
||||
/tmp/data/projects \
|
||||
/tmp/data/libext
|
||||
|
||||
# Download and install Rundeck
|
||||
WORKDIR /tmp
|
||||
RUN curl -Lo rundeck.war "https://repo1.maven.org/maven2/org/rundeck/rundeck/4.17.0/rundeck-4.17.0.war" && \
|
||||
mkdir -p /app/code/rundeck/webapps && \
|
||||
mv rundeck.war /app/code/rundeck/webapps/rundeck.war
|
||||
|
||||
# Copy configuration files
|
||||
COPY start.sh /app/code/
|
||||
COPY supervisord.conf /etc/supervisor/conf.d/supervisord.conf
|
||||
COPY nginx.conf /etc/nginx/sites-available/rundeck
|
||||
COPY realm.properties /tmp/data/etc/
|
||||
COPY framework.properties /tmp/data/etc/
|
||||
COPY rundeck-config.properties /tmp/data/etc/
|
||||
COPY jaas-ldap.conf /tmp/data/etc/
|
||||
COPY jaas-oidc.conf /tmp/data/etc/
|
||||
|
||||
# Configure NGINX
|
||||
RUN rm -f /etc/nginx/sites-enabled/default && \
|
||||
ln -sf /etc/nginx/sites-available/rundeck /etc/nginx/sites-enabled/rundeck
|
||||
|
||||
# Set permissions
|
||||
RUN chmod +x /app/code/start.sh && \
|
||||
chown -R cloudron:cloudron /app/code /app/data /tmp/data
|
||||
|
||||
WORKDIR /app/code
|
||||
|
||||
CMD ["/app/code/start.sh"]
|
@@ -0,0 +1,101 @@
|
||||
# Rundeck Cloudron Package Build Notes
|
||||
|
||||
## Overview
|
||||
This package deploys Rundeck, an open-source automation and job scheduling tool, on Cloudron. It uses PostgreSQL for data storage and can be configured to use either Cloudron's LDAP or OIDC for authentication.
|
||||
|
||||
## Package Contents
|
||||
- **CloudronManifest.json**: Defines the app for Cloudron
|
||||
- **Dockerfile**: Builds the container with Rundeck and dependencies
|
||||
- **start.sh**: Initializes the app and manages configuration
|
||||
- **nginx.conf**: Configures web server to proxy requests to Rundeck
|
||||
- **supervisord.conf**: Manages Rundeck and Nginx processes
|
||||
- **Configuration files**:
|
||||
- framework.properties: Core Rundeck configuration
|
||||
- rundeck-config.properties: Database and server settings
|
||||
- jaas-ldap.conf: LDAP authentication configuration
|
||||
- jaas-oidc.conf: OAuth/OIDC authentication configuration
|
||||
- realm.properties: Default user credentials
|
||||
|
||||
## Building the Package
|
||||
|
||||
1. Create a new directory for your Cloudron package
|
||||
2. Place all the files in this package in that directory
|
||||
3. Download a Rundeck logo and save it as `logo.png` in the package directory
|
||||
4. Build the package with the Cloudron CLI:
|
||||
```
|
||||
cloudron build
|
||||
```
|
||||
|
||||
## Testing
|
||||
|
||||
1. Install the package on a test Cloudron instance:
|
||||
```
|
||||
cloudron install --image [your-image-name]
|
||||
```
|
||||
2. After installation, access the app at its Cloudron URL
|
||||
3. Log in with the credentials shown in the post-install message
|
||||
4. Test basic functionality:
|
||||
- Create a project
|
||||
- Define a simple job
|
||||
- Run the job and verify it executes correctly
|
||||
- Check that logs are saved correctly
|
||||
5. Test authentication:
|
||||
- If LDAP is enabled, test login with a Cloudron user
|
||||
- If OIDC is enabled, test single sign-on functionality
|
||||
- Verify proper permissions mapping
|
||||
|
||||
## Deploying to Production
|
||||
|
||||
1. After successful testing, publish the package for your production Cloudron:
|
||||
```
|
||||
cloudron install --app rundeck --image [your-image-name]
|
||||
```
|
||||
2. Configure backup schedules through the Cloudron UI
|
||||
3. Update the admin password immediately after installation
|
||||
4. Configure necessary projects and jobs
|
||||
|
||||
## Authentication Configuration
|
||||
|
||||
The package supports two authentication methods:
|
||||
|
||||
### OIDC/OAuth (Preferred)
|
||||
- Automatically configured if Cloudron provides OAuth environment variables
|
||||
- Uses Cloudron's identity provider for single sign-on
|
||||
- User roles mapped from Cloudron groups
|
||||
- No additional configuration needed
|
||||
|
||||
### LDAP
|
||||
- Automatically configured if Cloudron provides LDAP environment variables
|
||||
- Uses Cloudron's LDAP server for authentication
|
||||
- Groups are mapped to Rundeck roles
|
||||
- Works with all Cloudron user accounts
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
- If the app fails to start, check the Cloudron logs:
|
||||
```
|
||||
cloudron logs -f
|
||||
```
|
||||
- Common issues:
|
||||
- Database connection problems: Check the PostgreSQL addon status
|
||||
- Authentication issues: Verify LDAP/OIDC configuration
|
||||
- File permissions: Ensure files in /app/data are owned by cloudron:cloudron
|
||||
- Memory limits: If Rundeck is slow or crashing, consider increasing the memory limit
|
||||
|
||||
## Updating the Package
|
||||
|
||||
1. Update the app version in CloudronManifest.json
|
||||
2. Update the Rundeck version in the Dockerfile
|
||||
3. Make any necessary changes to configuration files
|
||||
4. Rebuild and reinstall the package
|
||||
|
||||
## Backup and Restore
|
||||
|
||||
Cloudron automatically backs up the /app/data directory and PostgreSQL database. No additional configuration is required for backup functionality.
|
||||
|
||||
## Security Notes
|
||||
|
||||
- Rundeck stores sensitive data (credentials, private keys) in its database and file system
|
||||
- All sensitive data is stored in the /app/data directory, which is backed up by Cloudron
|
||||
- API keys and other secrets are encrypted using Jasypt encryption
|
||||
- Always use HTTPS (provided by Cloudron) for secure access
|
@@ -0,0 +1,57 @@
|
||||
# framework.properties
|
||||
#
|
||||
# The base directory for the rundeck server
|
||||
#
|
||||
rdeck.base=/app/data
|
||||
|
||||
# Indicates a file contains credentials for writing to the output log file.
|
||||
#
|
||||
# The contents of this file must contain a single line with 2 comma separated
|
||||
# strings:
|
||||
# <username>,<password>
|
||||
framework.output.password.file=/app/data/etc/output.password
|
||||
|
||||
# Framework crypto options
|
||||
# framework.crypto.keystore.filename=
|
||||
# framework.crypto.keystore.password=
|
||||
# framework.crypto.secretkey.password=
|
||||
|
||||
# SSH connection timeout after a specified number of milliseconds.
|
||||
# Default timeout is 30 seconds.
|
||||
framework.ssh.timeout=30000
|
||||
|
||||
# Set the follow to true if you want ssh-agent forwarding to work.
|
||||
framework.ssh.user.enableagentforward=false
|
||||
|
||||
# ssh key storage
|
||||
framework.ssh.keypath=/app/data/.ssh
|
||||
framework.ssh.keystore.path=/app/data/var/storage
|
||||
|
||||
# SSH authentication type (password or privateKey)
|
||||
framework.ssh.authentication=privateKey
|
||||
|
||||
# Set this to true to use the ssh-key storage for ssh plugin tests
|
||||
framework.ssh.fileCopier.use.storage=false
|
||||
|
||||
#
|
||||
# Extra environment variables to pass to throttled/queued commands
|
||||
#
|
||||
# comma separated list of environment variables to pass from parent process to
|
||||
# to child process as is
|
||||
framework.env.retain=JVM_OPTS
|
||||
|
||||
# API Tokens File
|
||||
framework.tokens.file=/app/data/etc/tokens.properties
|
||||
|
||||
# For Server URL and Port
|
||||
framework.server.name=Rundeck
|
||||
framework.server.hostname=${CLOUDRON_APP_DOMAIN}
|
||||
framework.server.port=443
|
||||
framework.server.url=https://${CLOUDRON_APP_DOMAIN}
|
||||
|
||||
# Define auth resources
|
||||
framework.authorization.resource.file.path=/app/data/etc/resources.xml
|
||||
|
||||
# Logging
|
||||
framework.log.dispatch.console.format=[%d{ISO8601}] %-5p %c{2} - %m%n
|
||||
framework.log.dispatch.file=/app/data/var/logs/rundeck.log
|
@@ -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";
|
||||
};
|
@@ -0,0 +1,12 @@
|
||||
oauth {
|
||||
org.rundeck.jaas.jetty.JettyRolePropertyFileLoginModule required
|
||||
debug="true"
|
||||
useFirstPass="true"
|
||||
supplementalRoles="user"
|
||||
file="/app/data/etc/realm.properties";
|
||||
|
||||
com.dtolabs.rundeck.jetty.jaas.JettyOIDCUserGroupsLoginModule required
|
||||
debug="true"
|
||||
useFirstPass="false"
|
||||
storePass="true";
|
||||
};
|
34
Cloudron/WorkInProgress/rundeck.knownelement.com/nginx.conf
Normal file
34
Cloudron/WorkInProgress/rundeck.knownelement.com/nginx.conf
Normal file
@@ -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;
|
||||
}
|
||||
}
|
@@ -0,0 +1,2 @@
|
||||
# Initial Admin User - will be set up by start.sh
|
||||
admin:admin,user,admin
|
@@ -0,0 +1,33 @@
|
||||
# rundeck-config.properties
|
||||
#
|
||||
|
||||
# Database connection
|
||||
dataSource.driverClassName = org.postgresql.Driver
|
||||
dataSource.url = ${RUNDECK_SERVER_DATASTORE_URL}
|
||||
dataSource.username = ${CLOUDRON_POSTGRESQL_USERNAME}
|
||||
dataSource.password = ${CLOUDRON_POSTGRESQL_PASSWORD}
|
||||
dataSource.dbCreate = update
|
||||
|
||||
# Plugin installation
|
||||
rundeck.plugin.dir = /app/data/libext
|
||||
|
||||
# Server settings
|
||||
grails.serverURL = https://${CLOUDRON_APP_DOMAIN}
|
||||
rundeck.gui.startpage = jobs
|
||||
rundeck.enableSelfSignedCertDownload = false
|
||||
rundeck.jetty.connector.forwarded = true
|
||||
rundeck.security.useHMacRequestTokens = true
|
||||
rundeck.security.csrf.referer.filterMethod = NONE
|
||||
rundeck.api.tokens.duration.max = 30d
|
||||
|
||||
# Logging
|
||||
rundeck.log4j.config.file = /app/data/server/config/log4j2.properties
|
||||
rundeck.logging.dir = /app/data/var/logs
|
||||
|
||||
# File storage
|
||||
rundeck.projectsStorageType=filesystem
|
||||
rundeck.storage.provider.1.type=file
|
||||
rundeck.storage.provider.1.path=/app/data/var/storage
|
||||
rundeck.storage.converter.1.type=jasypt-encryption
|
||||
rundeck.storage.converter.1.key=keys
|
||||
rundeck.storage.converter.1.path=keys
|
104
Cloudron/WorkInProgress/rundeck.knownelement.com/start.sh
Normal file
104
Cloudron/WorkInProgress/rundeck.knownelement.com/start.sh
Normal file
@@ -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 }}|<existing 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
|
@@ -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
|
@@ -0,0 +1 @@
|
||||
We need an SSH portal. Use xterm.js to find solutions.
|
Reference in New Issue
Block a user