resgrid package

This commit is contained in:
2025-04-21 16:04:31 -04:00
parent eea38e1653
commit 24757c5cf5
11 changed files with 571 additions and 4 deletions

View File

@@ -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 }}"
}
}

View 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"]

View File

@@ -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 Cloudrons OIDC provider
- Users who log in via SSO will be created in Resgrid automatically
- Youll 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)

View 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";
}
}

View File

@@ -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

View 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

View File

@@ -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

View File

@@ -1 +0,0 @@
# resgrid docker compose for tsys

View File

@@ -1 +0,0 @@
This directory contains template files for the application at FQDN indidicated by the parent directory. They will be processed using mo (bash mustache).

View File

@@ -1 +0,0 @@
This directory contains final docker compose files for the application at FQDN indidicated by the parent directory.

View File

@@ -1 +0,0 @@
This directory contains files from the vendor unmodified. They serve as a base for the input-files sibling directory