Fresh start without sensitive data

This commit is contained in:
admin 2025-05-11 16:05:18 -06:00
commit 917463e75e
332 changed files with 126989 additions and 0 deletions

113
.env Normal file
View File

@ -0,0 +1,113 @@
# Never share this file publicly. It contains sensitive information.
# This file is used to configure various applications and services.
# Generated by Changemaker Config Wizard on Thu 08 May 2025 03:22:28 PM MDT
# Domain Configuration
DOMAIN=test.com
BASE_DOMAIN=https://test.com
# Listmonk Configuration
LISTMONK_ADMIN_USER=admin
LISTMONK_ADMIN_PASSWORD=strongpassword
LISTMONK_PORT=9000
LISTMONK_HOSTNAME=listmonk.test.com
# Database Credentials
POSTGRES_USER=listmonk
POSTGRES_PASSWORD=7Cl6OUA6KrJ1fQ0l/ZwJ
POSTGRES_DB=listmonk
# Monica CRM Configuration
MONICA_APP_KEY=base64:NUdzZlhaOVR5M0FEd0JNZGhEcUFZbDBFdmlHbEhUYzc=
MONICA_DB_USERNAME=monica
MONICA_DB_PASSWORD=s6ikjtkdmk3HQnTX58tO
MONICA_MYSQL_DATABASE=monica
MONICA_MYSQL_USER=monica
MONICA_MYSQL_PASSWORD=s6ikjtkdmk3HQnTX58tO
# MkDocs Configuration
USER_ID=1000
GROUP_ID=1000
MKDOCS_PORT=4000
# Flatnotes Configuration
FLATNOTES_PUID=1000
FLATNOTES_PGID=1000
FLATNOTES_AUTH_TYPE=password
FLATNOTES_USERNAME=user
FLATNOTES_PASSWORD=changeMe!
FLATNOTES_SECRET_KEY=S1SfMQwbkxvYC+SIAJkf4v6fJ0DJWJrU
FLATNOTES_PORT=8089
# Gitea Configuration
GITEA_DB_TYPE=mysql
GITEA_DB_HOST=gitea-db:3306
GITEA_DB_NAME=gitea
GITEA_DB_USER=gitea
GITEA_DB_PASSWD=0OmqfwcnPCWbsNbg8upAQ7Zh
GITEA_DB_ROOT_PASSWORD=Ygl6RyjoJbNwOd2p9yiVc3+2
GITEA_WEB_PORT=3030
GITEA_SSH_PORT=2225
GITEA_ROOT_URL=https://gitea.test.com
GITEA_DOMAIN=gitea.test.com
# Apache Answer Configuration
ANSWER_APP_PORT=9080
# Excalidraw Configuration
EXCALIDRAW_PORT=3333
EXCALIDRAW_LIBRARY_URL=https://libraries.excalidraw.com
EXCALIDRAW_LIBRARY_BACKEND=https://us-central1-excalidraw-room-persistence.cloudfunctions.net/libraries # do not alter this URL
EXCALIDRAW_PUBLIC_URL=https://excalidraw.test.com
EXCALIDRAW_PUBLIC_SOCKET_URL=https://excalidraw.test.com
# Code Server Configuration
CODE_SERVER_PORT=8888
USER_NAME=coder
# Cloudflare Credentials
CF_AUTH_EMAIL=[insert]
CF_API_TOKEN=[insert]
CF_ZONE_ID=[insert]
CF_TUNNEL_ID=[insert]
CF_DOMAIN=[insert]
# NocoDB Configuration
NOCODB_PORT=8090
NOCODB_JWT_SECRET=QUwWUpyZ/XjPm9sBhjkwI5X3XANFzigW
NOCODB_DB_NAME=nocodb
NOCODB_DB_USER=noco
NOCODB_DB_PASSWORD=qKd+v98CPRViaOHHV+ZJ
# OpenWebUI Configuration
OPEN_WEBUI_PORT=3005
OPEN_WEBUI_URL=https://open-webui.test.com
# N8N Configuration
N8N_PORT=5678
N8N_HOST=n8n.test.com
N8N_ENCRYPTION_KEY=PRp6GXqr+ShtN/SEJHTKuOifEBLcaruC
N8N_USER_EMAIL=admin@example.com
N8N_USER_PASSWORD=changeMe
GENERIC_TIMEZONE=UTC
# ConvertX Configuration
CONVERTX_PORT=3100
CONVERTX_JWT_SECRET=d71go1i0k1ytW37z+ongq78HlwsVdS1sqdGoxSBux3WxvH1f
# Rocket.Chat Configuration
ROCKETCHAT_IMAGE=registry.rocket.chat/rocketchat/rocket.chat
ROCKETCHAT_RELEASE=latest
ROCKETCHAT_PORT=3004
ROCKETCHAT_CONTAINER_PORT=3000
ROCKETCHAT_ROOT_URL=https://rocket.test.com
ROCKETCHAT_DEPLOYMENT_ENVIRONMENT=production
ROCKETCHAT_MONGODB_VERSION=6.0
ROCKETCHAT_MONGODB_HOST=mongodb-rocketchat
ROCKETCHAT_MONGODB_PORT=27017
ROCKETCHAT_MONGODB_DATABASE=rocketchat
ROCKETCHAT_MONGODB_REPLICA_SET=rs0
ROCKETCHAT_MONGODB_ENABLE_JOURNAL=true
ROCKETCHAT_MONGODB_ALLOW_EMPTY_PASSWORD=yes
# Additional Configuration

41
.gitignore vendored Executable file
View File

@ -0,0 +1,41 @@
# Ignore all files in specific directories but keep .gitkeep files
# code-server directories
configs/code-server/.config/code-server/*
!configs/code-server/.config/code-server/.gitkeep
configs/code-server/.local/*
!configs/code-server/.local/.gitkeep
# ferdium directory
configs/ferdium/*
!configs/ferdium/.gitkeep
# flatnotes directory
mkdocs/docs/blog/posts/.flatnotes/*
!mkdocs/docs/blog/posts/.flatnotes/.gitkeep
# attachments directory
mkdocs/docs/blog/posts/attachments/*
!mkdocs/docs/blog/posts/attachments/.gitkeep
# data directory
data/*
!data/.gitkeep
# local-files
local-files/*
!local-files/.gitkeep
# Convertx
convertx-data/*
!convertx-data/.gitkeep
# Env Backups
.env.backup*
# answers data
answer-data/*
!answer-data/.gitkeep
.vscode

84
Dockerfile.code-server Normal file
View File

@ -0,0 +1,84 @@
FROM codercom/code-server:latest
USER root
# Install Python and dependencies
RUN apt-get update && apt-get install -y \
python3 \
python3-pip \
python3-venv \
python3-full \
pipx \
# Dependencies for CairoSVG and Pillow (PIL)
libcairo2-dev \
libfreetype6-dev \
libffi-dev \
libjpeg-dev \
libpng-dev \
libz-dev \
python3-dev \
pkg-config \
# Additional dependencies for advanced image processing
libwebp-dev \
libtiff5-dev \
libopenjp2-7-dev \
liblcms2-dev \
libxml2-dev \
libxslt1-dev \
# PDF generation dependencies
weasyprint \
fonts-roboto \
# Git for git-based plugins
git \
# For lxml
zlib1g-dev \
# Required for some plugins
build-essential \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*
# Switch to non-root user (coder)
USER coder
# Set up a virtual environment for mkdocs
RUN mkdir -p /home/coder/.venv
RUN python3 -m venv /home/coder/.venv/mkdocs
# Install mkdocs-material in the virtual environment with all extras
RUN /home/coder/.venv/mkdocs/bin/pip install "mkdocs-material[imaging,recommended,git]"
# Install additional useful MkDocs plugins
RUN /home/coder/.venv/mkdocs/bin/pip install \
mkdocs-minify-plugin \
mkdocs-git-revision-date-localized-plugin \
mkdocs-glightbox \
mkdocs-redirects \
mkdocs-awesome-pages-plugin \
mkdocs-blog-plugin \
mkdocs-rss-plugin \
mkdocs-meta-descriptions-plugin \
mkdocs-swagger-ui-tag \
mkdocs-macros-plugin \
mkdocs-material-extensions \
mkdocs-section-index \
mkdocs-table-reader-plugin \
mkdocs-pdf-export-plugin \
mkdocs-mermaid2-plugin \
pymdown-extensions \
pygments \
pillow \
cairosvg
# Add the virtual environment bin to PATH
ENV PATH="/home/coder/.venv/mkdocs/bin:${PATH}"
# Add shell configuration to activate the virtual environment in .bashrc
RUN echo 'export PATH="/home/coder/.venv/mkdocs/bin:$PATH"' >> ~/.bashrc
RUN echo 'export PATH="/home/coder/.local/bin:$PATH"' >> ~/.bashrc
# Create a convenience script to simplify running mkdocs commands
RUN mkdir -p /home/coder/.local/bin \
&& echo '#!/bin/bash\ncd /home/coder/mkdocs\nmkdocs "$@"' > /home/coder/.local/bin/run-mkdocs \
&& chmod +x /home/coder/.local/bin/run-mkdocs
WORKDIR /home/coder

347
README.md Executable file
View File

@ -0,0 +1,347 @@
# Changemaker V5
![changemaker](/assets/images/changemaker.png)
Changemaker V5 is a battle-tested, lightweight, self-hosted productivity suite which empowers you to deploy secure, locally-built websites, blogs, newsletters, & forms from personal projects to full-fledged campaigns granting you complete control, inherent security, and true freedom of speech.
It is a project undertaken by The Bunker Operations, headquarted in Edmonton, Alberta, Canada, as to provide our community a digital campaign alternative to mainstream American systems.
---
## Currated Suite of Applications
![homepage](/assets/images/homepage.png)
---
## Contents
- [Prerequisites](#prerequisites)
- [Quick Start](#quick-start)
- [Detailed Installation](#detailed-installation)
- [1. Install Docker and Docker Compose](#1-install-docker-and-docker-compose)
- [2. Clone the Repository](#2-clone-the-repository)
- [3. Configure Your Environment](#3-configure-your-environment)
- [4. Start the Services](#4-start-the-services)
- [5. Run Post-Installation Tasks](#5-run-post-installation-tasks)
- [Local Service Ports](#local-service-ports)
- [Cloudflare Tunnel Setup](#cloudflare-tunnel-setup)
- [Install Cloudflared on Ubuntu 24.04](#install-cloudflared-on-ubuntu-2404)
- [Configure Your Cloudflare Tunnel](#configure-your-cloudflare-tunnel)
- [Create a Cloudflare System Service](#create-a-cloudflare-system-service)
- [Add CNAME Records](#add-cname-records)
- [Website Build and Deployment Workflow](#website-build-and-deployment-workflow)
- [Reset Your Installation](#reset-your-installation)
- [Accessing Your Services](#accessing-your-services)
- [Troubleshooting](#troubleshooting)
---
## Development Pathway
Changemaker's identified wants for development:
- Internal integrations for assset management i.e. shared plain file locations
- Database connections for automation systems i.e. manauls for Nocodb & n8n on connecting services
- Manual & landing site for the whole system i.e. upgrading bnkops.com
- Trainings and manuals across the board
Idenitfied Feature Requests:
- Event Management: Looking at [hi.ewvents](https://hi.events/)
- Scheduling: Looking at [rally](https://rallly.co/)
- Support and user chat: looking at [chatwoot](https://github.com/chatwoot/chatwoot)
- Mass community chat: looking at [thelounge](https://thelounge.chat/)
- Team chat and project management: looking at [rocket chat](https://github.com/RocketChat/Rocket.Chat) ✔️
Bugs:
- Readme needs a full flow redo - ✅ next up
- Config script needs to be updated for nocodb for a simpler string / set the string - :white_check_mark:
- Gitea DNS application access bypass not properly setting - ✅ bypass needing manual setup / need to explore api more
- Portainer not serving to http - 🤔 portainer to be limited to local access
- nocodb setup upping odd - ✅ password needs no special characters
- ferdium port mismatch - ✅ was a cloudflare port setting missmatch
## Prerequisites
- A Linux server (Ubuntu 22.04/24.04 recommended)
- Docker & Docker Compose
- Internet connection
- (Optional) Root or sudo access
- (Optional) A domain name for remote access
- (Optional) Cloudflare account for tunnel setup
## Quick Start for Local Dev
Review all off the applications [here](/apps.md)
If you're familiar with Docker and want to get started quickly:
```bash
# Clone the repository
git clone https://gitea.bnkhome.org/bnkops/Changemaker.git
cd changemaker
```
```bash
# Use default configuration for development or run the config script for configuration
# To optionally configure, first make the script executable:
chmod +x config.sh
# Then run the configuration script:
./config.sh
```
```
# Start all services
docker compose up -d
```
**[!Warning] Configure Portainer & Install Gitea**
Portainer has a timed build process. Make sure to immediatly configure the service by visiting https://localhost:9444
Gitea has a install process that you should complete on first build.
**First time installation can take several miniutes**
On a 1GB internet connection, instal time is approximately 3 minutes.
## Local Service Ports
When running Changemaker locally, you can access the services at the following ports on your server:
| Service | Local Port | Local URL |
|--------------|------------|------------------------------------------|
| Root (Nginx) | 4001 | [http://localhost:4001](http://localhost:4001) |
| Homepage | 3010 | [http://localhost:3010](http://localhost:3010) |
| Excalidraw | 3333 | [http://localhost:3333](http://localhost:3333) |
| Listmonk | 9000 | [http://localhost:9000](http://localhost:9000) |
| Monica CRM | 8085 | [http://localhost:8085](http://localhost:8085) |
| MkDocs | 4000 | [http://localhost:4000](http://localhost:4000) |
| Flatnotes | 8089 | [http://localhost:8089](http://localhost:8089) |
| Code Server | 8888 | [http://localhost:8888](http://localhost:8888) |
| Ollama | 11435 | [http://localhost:11435](http://localhost:11435) |
| OpenWebUI | 3005 | [http://localhost:3005](http://localhost:3005) |
| Gitea | 3030 | [http://localhost:3030](http://localhost:3030) |
| Portainer | 8005 | [http://localhost:8005](http://localhost:8005) |
| Mini QR | 8081 | [http://localhost:8081](http://localhost:8081) |
| Ferdium | 3006 | [http://localhost:3006](http://localhost:3006) |
| Answer | 9080 | [http://localhost:9080](http://localhost:9080) |
| NocoDB | 8090 | [http://localhost:8090](http://localhost:8090) |
| n8n | 5678 | [https://localhost:5678](https://localhost:5678) |
| ConvertX | 3100 | [http://localhost:3100](http://localhost:3100) |
| Rocket.Chat | 3004 | [http://localhost:3004](http://localhost:3004) |
## Detailed Installation
### Ubuntu OS & Build Outs
You can deploy Changemaker on any OS using Docker however we also provide several full Ubuntu build-outs. These scripts can speed up your deployment immensely and Changemaker is developed on a like system:
1. **[build.server](https://gitea.bnkhome.org/bnkops/scripts/src/branch/main/build.server.md)** - this build-out is a lightweight deployment aimed for dedicated server machines. It is focused on entry level users who would build on a dedicated machine.
2. **[build.homelab](https://gitea.bnkhome.org/bnkops/scripts/src/branch/main/build.homelab.md)** - this build-out is full-some development focused build-out that The Bunker Operations uses for our day-to-day operations.
Configuration and services scripts for futher developing the system can be found at the [scripts](https://gitea.bnkhome.org/bnkops/scripts) repo.
### 1. Install Docker and Docker Compose
Install Docker and Docker Compose on your system if they're not already installed:
[Install Docker & Docker Compose](https://gitea.bnkhome.org/bnkops/scripts/src/branch/main/build.homelab.md#dockerhttpswwwdockercom)
Verify that Docker and Docker Compose are installed correctly:
```bash
docker --version
docker compose version
```
### 2. Clone the Repository
```bash
git clone https://github.com/your-org/changemaker-v5.git
cd changemaker-v5
```
### 2. Configure Your Environment
#### Setting Up Cloudflare Credentials
To use the script, you'll need to collect several Cloudflare variables:
1. **Create an API Token with appropriate permissions**:
- Go to your [Cloudflare Dashboard](https://dash.cloudflare.com/) → Profile → API Tokens
- Click "Create Token"
- Either use the "Edit zone DNS" template or create a custom token with:
- Zone:DNS:Edit permissions
- Access:Apps:Edit permissions
- Restrict the token to only your specific zone/domain
- Generate and copy the token
2. **Get your Zone ID**:
- Go to your domain's overview page in the Cloudflare dashboard
- The Zone ID is displayed on the right sidebar
- It looks like: `023e105f4ecef8ad9ca31a8372d0c353`
3. **Get your Tunnel ID**:
- You should have noted your tunnel id in your tunnel creation or you can find it through cloudflare or in your files:
- Go to Cloudflare Zero Trust dashboard → Access → Tunnels
- Click on your tunnel
- The Tunnel ID is in the URL: `https://dash.teams.cloudflare.com/xxx/network/tunnels/xxxx`
- It looks like: `6ff42ae2-765d-4adf-8112-31c55c1551ef`
You have two options:
**Option A: Use the configuration wizard (recommended)**
```bash
# Make the script executable
chmod +x config.sh
# Run the configuration wizard
./config.sh
```
**Option B: Configure manually**
```bash
# Edit the .env file with your settings
nano .env
```
### 4. Start the Services
```bash
# Pull and start all containers in detached mode
docker compose up -d
```
> [!Warning] Configure Portainer
Portainer has a timed build process. Make sure to immediatly configure the service at https://localhost:9444 following successful build.
All services can now be accessed through on local machine. If deploying to public, it is recommended to **configure portainer** and then continue configuration for all other services once tunnel is established. Then use the public links for configuration of services. For online deployment with Cloudflare, continue to next steps.
### 4. Cloudflare Tunnel Setup
For secure remote access to your services, you can set up a Cloudflare Tunnel.
### Install Cloudflared on Ubuntu 24.04
[Cloudflared Installation Guide](https://gitea.bnkhome.org/bnkops/scripts/src/branch/main/build.homelab.md#cloudflaredhttpsdeveloperscloudflarecomcloudflare-oneconnectionsconnect-networks)
### Configure Your Cloudflare Tunnel
You can use our [Cloudflare Configuration Guide](https://gitea.bnkhome.org/bnkops/scripts/src/branch/main/config.cloudflare.homelab.md) however remember to copy the values of the [example config](/example.cloudflare.config.yml) for this deployment.
### Create a Cloudflare System Service
[Cloudflare Service Setup Guide](https://gitea.bnkhome.org/bnkops/scripts/src/branch/main/service.cloudflared.md)
### Add CNAME Records
After setting up your Cloudflare Tunnel, you need to add CNAME records for your services. You can do this manually in the Cloudflare DNS panel or with using the following script: `add-cname-records.sh`
```bash
# Make the script executable
chmod +x add-cname-records.sh
# Run the script to add CNAME records
./add-cname-records.sh
```
This script will add CNAME records for all Changemaker services to your Cloudflare DNS.
It will also set up a Cloudflare Access Application for all services execpt for your website and gitea. This is a extra layer of security that we do recommend for your deployment. It will automatically allow any emails with from the root domain that you set in the `config.sh` process. For example, if you set your root domain to `example.com` your access rule will allow emails ending with @example.com thorugh. You can update your access settings in the Cloudflare Zero Trust dashboard.
> [!warning] Cloudflare Zero Trust
To ensure that system is secure, we highly recommend setting up some level of access control using Cloudflare Zero Trust. The `add-cname-records.sh` will do this automatically however the user is encouraged to familiarize themselves with Cloudflares Zero Trust access system.
## Website Build and Deployment Workflow
Changemaker uses MkDocs to create your website content, which is then served by an Nginx server. To update your website, you need to:
1. **Edit your content** using either the Code Server or locally on your machine
2. **Build the static site files**
3. **Let the Nginx server (mkdocs-site-server) serve the built site**
### Building Your Website
You can build your website in two ways:
#### Option 1: Using Code Server (recommended for remote deployments)
1. Access Code Server at http://localhost:8888 or https://code-server.yourdomain.com
2. Navigate to the mkdocs directory `/home/coder/mkdocs/`
3. Open a terminal in Code Server
4. Run the build command:
```bash
cd /home/coder/mkdocs
mkdocs build
```
#### Option 2: Locally on your machine
1. Navigate to the mkdocs directory in your project:
```bash
cd /home/bunker-admin/Changemaker/mkdocs
```
2. Run the build command:
```bash
mkdocs build
```
After building, the static site files will be generated in the `mkdocs/site` directory, which is automatically mounted to the Nginx server (mkdocs-site-server). Your website will be immediately available at:
- Locally: http://localhost:4001
- With Cloudflare: https://yourdomain.com
### Development vs Production
- During **development**, you can use the MkDocs live server at port 4000, which automatically rebuilds when you make changes
- For **production**, build your site as described above and let the Nginx server at port 4001 serve the static files
## Accessing Your Services
The **Homepage** acts as a central dashboard for all your Changemaker services. You can access it at:
- Locally: http://localhost:3010 or http://your-server-ip:3010
- With Cloudflare: https://homepage.yourdomain.com
The Homepage will display links to all your deployed services, making it easy to navigate your Changemaker ecosystem.
After installation and cloudflare deployment you can also access individual services at the following URLs:
- Website: https://yourdomain.com
- Homepage: https://homepage.yourdomain.com
- Excalidraw: https://excalidraw.yourdomain.com
- Listmonk: https://listmonk.yourdomain.com
- Monica CRM: https://monica.yourdomain.com
- MkDocs: https://yourdomain.com
- Flatnotes: https://flatnotes.yourdomain.com
- Code Server: https://code-server.yourdomain.com
- Ollama: https://ollama.yourdomain.com
- OpenWebUI: https://open-web-ui.yourdomain.com
- Gitea: https://gitea.yourdomain.com
- Portainer: https://portainer.yourdomain.com
- Mini QR: https://mini-qr.yourdomain.com
- Ferdium: https://ferdium.yourdomain.com
- Answer: https://answer.yourdomain.com
- NocoDB: https://nocodb.yourdomain.com
- n8n: https://n8n.yourdomain.com
- ConvertX: https://convertx.yourdomain.com
- Rocket.Chat: https://rocket.yourdomain.com
## Troubleshooting
If you encounter issues:
1. Check the Docker logs:
```bash
docker compose logs
```
2. Verify service status:
```bash
docker compose ps
```
3. Ensure your Cloudflare Tunnel is running:
```bash
sudo systemctl status cloudflared
```
4. Check CNAME records in your Cloudflare dashboard.
For additional help, please file an issue on our GitHub repository.

238
add-cname-records.sh Executable file
View File

@ -0,0 +1,238 @@
#!/bin/bash
echo "#############################################################"
echo "# "
echo "# WARNING: This script will REPLACE ALL DNS records at "
echo "# the target domain ($CF_DOMAIN)! "
echo "# "
echo "# All existing DNS records for the listed subdomains will "
echo "# be deleted and replaced with new CNAME records. "
echo "# "
echo "#############################################################"
echo ""
echo "-------------------------------------------------------------"
echo "Cloudflare Credentials Required"
echo "Please ensure your .env file contains the following variables:"
echo " CF_API_TOKEN=your_cloudflare_api_token"
echo " CF_ZONE_ID=your_cloudflare_zone_id"
echo " CF_TUNNEL_ID=your_cloudflared_tunnel_id"
echo " CF_DOMAIN=yourdomain.com"
echo ""
echo "You can find these values in your Cloudflare dashboard:"
echo " - API Token: https://dash.cloudflare.com/profile/api-tokens (Create a token with Zone:DNS:Edit and Access:Apps:Edit permissions for your domain)"
echo " - Zone ID: On your domain's overview page"
echo " - Tunnel ID: In the Zero Trust dashboard under Access > Tunnels"
echo " - Domain: The domain you want to use for your services"
echo ""
echo "-------------------------------------------------------------"
echo ""
read -p "Type 'y' to continue or any other key to abort: " consent
if [[ "$consent" != "y" && "$consent" != "Y" ]]; then
echo "Aborted by user."
exit 1
fi
# Source environment variables from the .env file in the same directory
ENV_FILE="$(dirname "$0")/.env"
if [ -f "$ENV_FILE" ]; then
export $(grep -v '^#' "$ENV_FILE" | xargs)
else
echo "Error: .env file not found at $ENV_FILE"
exit 1
fi
# Check if required Cloudflare variables are set
if [ -z "$CF_API_TOKEN" ] || [ -z "$CF_ZONE_ID" ] || [ -z "$CF_TUNNEL_ID" ] || [ -z "$CF_DOMAIN" ]; then
echo "Error: One or more required Cloudflare environment variables (CF_API_TOKEN, CF_ZONE_ID, CF_TUNNEL_ID, CF_DOMAIN) are not set in $ENV_FILE."
exit 1
fi
# Check if jq is installed
if ! command -v jq &> /dev/null; then
echo "Error: jq is required but not installed. Please install jq to continue."
echo "On Debian/Ubuntu: sudo apt-get install jq"
echo "On RHEL/CentOS: sudo yum install jq"
exit 1
fi
# Array of subdomains based on docker-compose.yml services
SUBDOMAINS=(
"homepage"
"excalidraw"
"listmonk"
"monica"
"flatnotes"
"code-server"
"ollama"
"open-webui"
"gitea"
"mini-qr"
"ferdium"
"answer"
"nocodb"
"n8n"
"convertx"
"rocket"
"live"
)
# First, remove existing DNS records for these subdomains
echo "Removing existing DNS records..."
for subdomain in "${SUBDOMAINS[@]}"; do
echo "Checking for existing records for $subdomain.$CF_DOMAIN..."
# Get all DNS records for this subdomain
RECORDS=$(curl -s -X GET "https://api.cloudflare.com/client/v4/zones/$CF_ZONE_ID/dns_records?name=$subdomain.$CF_DOMAIN" \
-H "Authorization: Bearer $CF_API_TOKEN" \
-H "Content-Type: application/json")
# Extract record IDs
RECORD_IDS=$(echo $RECORDS | jq -r '.result[].id')
# Delete each record
for record_id in $RECORD_IDS; do
echo "Deleting record $record_id for $subdomain.$CF_DOMAIN..."
curl -s -X DELETE "https://api.cloudflare.com/client/v4/zones/$CF_ZONE_ID/dns_records/$record_id" \
-H "Authorization: Bearer $CF_API_TOKEN" \
-H "Content-Type: application/json"
done
done
echo "All existing records have been removed."
# Add CNAME records for each subdomain
for subdomain in "${SUBDOMAINS[@]}"; do
echo "Adding CNAME record for $subdomain.$CF_DOMAIN..."
curl -X POST "https://api.cloudflare.com/client/v4/zones/$CF_ZONE_ID/dns_records" \
-H "Authorization: Bearer $CF_API_TOKEN" \
-H "Content-Type: application/json" \
--data "{
\"type\": \"CNAME\",
\"name\": \"$subdomain\",
\"content\": \"$CF_TUNNEL_ID.cfargotunnel.com\",
\"ttl\": 1,
\"proxied\": true
}"
echo -e "\n"
done
echo "All CNAME records have been added."
# Add root domain record
echo "Adding root domain (@ record)..."
curl -X POST "https://api.cloudflare.com/client/v4/zones/$CF_ZONE_ID/dns_records" \
-H "Authorization: Bearer $CF_API_TOKEN" \
-H "Content-Type: application/json" \
--data "{
\"type\": \"CNAME\",
\"name\": \"@\",
\"content\": \"$CF_TUNNEL_ID.cfargotunnel.com\",
\"ttl\": 1,
\"proxied\": true
}"
echo -e "\n"
echo "Root domain CNAME record has been added."
# Now create the Cloudflare Access applications
echo "Creating Cloudflare Access applications..."
# 1. Create wildcard access application for all subdomains
echo "Creating wildcard access application for *.$CF_DOMAIN..."
WILDCARD_APP_RESPONSE=$(curl -s -X POST "https://api.cloudflare.com/client/v4/zones/$CF_ZONE_ID/access/apps" \
-H "Authorization: Bearer $CF_API_TOKEN" \
-H "Content-Type: application/json" \
--data "{
\"name\": \"All Applications - $CF_DOMAIN\",
\"domain\": \"*.$CF_DOMAIN\",
\"type\": \"self_hosted\",
\"session_duration\": \"24h\",
\"app_launcher_visible\": true,
\"skip_interstitial\": true
}")
# Extract the application ID from the response
WILDCARD_APP_ID=$(echo $WILDCARD_APP_RESPONSE | jq -r '.result.id')
if [ -z "$WILDCARD_APP_ID" ] || [ "$WILDCARD_APP_ID" == "null" ]; then
echo "Error creating wildcard access application. Response: $WILDCARD_APP_RESPONSE"
else
echo "Successfully created wildcard access application with ID: $WILDCARD_APP_ID"
# Create policy for emails ending with the domain
echo "Creating email domain policy for wildcard application..."
EMAIL_DOMAIN=$(echo $CF_DOMAIN | cut -d'.' -f1,2)
curl -s -X POST "https://api.cloudflare.com/client/v4/zones/$CF_ZONE_ID/access/apps/$WILDCARD_APP_ID/policies" \
-H "Authorization: Bearer $CF_API_TOKEN" \
-H "Content-Type: application/json" \
--data "{
\"name\": \"Allow Domain Emails\",
\"decision\": \"allow\",
\"include\": [{
\"email_domain\": {
\"domain\": \"$EMAIL_DOMAIN\"
}
}],
\"require\": [],
\"exclude\": [],
\"precedence\": 1,
\"purpose\": \"Authentication for domain users\",
\"session_duration\": \"24h\"
}"
echo "Email domain policy created."
fi
# 2. Create specific access application for Gitea
echo "Creating access application for gitea.$CF_DOMAIN..."
GITEA_APP_RESPONSE=$(curl -s -X POST "https://api.cloudflare.com/client/v4/zones/$CF_ZONE_ID/access/apps" \
-H "Authorization: Bearer $CF_API_TOKEN" \
-H "Content-Type: application/json" \
--data "{
\"name\": \"Gitea $CF_DOMAIN\",
\"domain\": \"gitea.$CF_DOMAIN\",
\"type\": \"self_hosted\",
\"app_launcher_visible\": true,
\"skip_interstitial\": true
}")
# Extract the application ID from the response
GITEA_APP_ID=$(echo $GITEA_APP_RESPONSE | jq -r '.result.id')
if [ -z "$GITEA_APP_ID" ] || [ "$GITEA_APP_ID" == "null" ]; then
echo "Error creating Gitea access application. Response: $GITEA_APP_RESPONSE"
else
echo "Successfully created Gitea access application with ID: $GITEA_APP_ID"
# Create bypass policy for everyone - Updated format
echo "Creating bypass policy for Gitea application..."
POLICY_RESPONSE=$(curl -s -X POST "https://api.cloudflare.com/client/v4/zones/$CF_ZONE_ID/access/apps/$GITEA_APP_ID/policies" \
-H "Authorization: Bearer $CF_API_TOKEN" \
-H "Content-Type: application/json" \
--data "{
\"name\": \"Bypass for Everyone\",
\"decision\": \"bypass\",
\"include\": [{
\"everyone\": {}
}],
\"require\": [],
\"exclude\": []
}")
# Check if policy creation was successful
POLICY_SUCCESS=$(echo $POLICY_RESPONSE | jq -r '.success')
if [ "$POLICY_SUCCESS" == "true" ]; then
POLICY_ID=$(echo $POLICY_RESPONSE | jq -r '.result.id')
echo "Bypass policy for Gitea created successfully with ID: $POLICY_ID"
else
ERROR_MSG=$(echo $POLICY_RESPONSE | jq -r '.errors[0].message')
echo "Error creating bypass policy for Gitea: $ERROR_MSG"
echo "Full response: $POLICY_RESPONSE"
fi
fi
echo "Cloudflare Access applications setup complete."

0
answer-data/.gitkeep Normal file
View File

1384
answer-data/i18n/af_ZA.yaml Normal file

File diff suppressed because it is too large Load Diff

1384
answer-data/i18n/ar_SA.yaml Normal file

File diff suppressed because it is too large Load Diff

1371
answer-data/i18n/az_AZ.yaml Normal file

File diff suppressed because it is too large Load Diff

1371
answer-data/i18n/bal_BA.yaml Normal file

File diff suppressed because it is too large Load Diff

1371
answer-data/i18n/ban_ID.yaml Normal file

File diff suppressed because it is too large Load Diff

1371
answer-data/i18n/bn_BD.yaml Normal file

File diff suppressed because it is too large Load Diff

1371
answer-data/i18n/bs_BA.yaml Normal file

File diff suppressed because it is too large Load Diff

1384
answer-data/i18n/ca_ES.yaml Normal file

File diff suppressed because it is too large Load Diff

2319
answer-data/i18n/cs_CZ.yaml Normal file

File diff suppressed because it is too large Load Diff

2319
answer-data/i18n/cy_GB.yaml Normal file

File diff suppressed because it is too large Load Diff

2319
answer-data/i18n/da_DK.yaml Normal file

File diff suppressed because it is too large Load Diff

2319
answer-data/i18n/de_DE.yaml Normal file

File diff suppressed because it is too large Load Diff

1384
answer-data/i18n/el_GR.yaml Normal file

File diff suppressed because it is too large Load Diff

2489
answer-data/i18n/en_US.yaml Normal file

File diff suppressed because it is too large Load Diff

2319
answer-data/i18n/es_ES.yaml Normal file

File diff suppressed because it is too large Load Diff

2319
answer-data/i18n/fa_IR.yaml Normal file

File diff suppressed because it is too large Load Diff

1384
answer-data/i18n/fi_FI.yaml Normal file

File diff suppressed because it is too large Load Diff

2319
answer-data/i18n/fr_FR.yaml Normal file

File diff suppressed because it is too large Load Diff

1384
answer-data/i18n/he_IL.yaml Normal file

File diff suppressed because it is too large Load Diff

2319
answer-data/i18n/hi_IN.yaml Normal file

File diff suppressed because it is too large Load Diff

1384
answer-data/i18n/hu_HU.yaml Normal file

File diff suppressed because it is too large Load Diff

1371
answer-data/i18n/hy_AM.yaml Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,64 @@
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
# all support language
language_options:
- label: "English"
value: "en_US"
progress: 100
- label: "Español"
value: "es_ES"
progress: 96
- label: "Português(BR)"
value: "pt_BR"
progress: 96
- label: "Português"
value: "pt_PT"
progress: 96
- label: "Deutsch"
value: "de_DE"
progress: 96
- label: "Français"
value: "fr_FR"
progress: 96
- label: "日本語"
value: "ja_JP"
progress: 96
- label: "Italiano"
value: "it_IT"
progress: 96
- label: "Русский"
value: "ru_RU"
progress: 80
- label: "简体中文"
value: "zh_CN"
progress: 100
- label: "繁體中文"
value: "zh_TW"
progress: 47
- label: "한국어"
value: "ko_KR"
progress: 73
- label: "Tiếng Việt"
value: "vi_VN"
progress: 96
- label: "Slovak"
value: "sk_SK"
progress: 45
- label: "فارسی"
value: "fa_IR"
progress: 69

2319
answer-data/i18n/id_ID.yaml Normal file

File diff suppressed because it is too large Load Diff

2319
answer-data/i18n/it_IT.yaml Normal file

File diff suppressed because it is too large Load Diff

2320
answer-data/i18n/ja_JP.yaml Normal file

File diff suppressed because it is too large Load Diff

2319
answer-data/i18n/ko_KR.yaml Normal file

File diff suppressed because it is too large Load Diff

2319
answer-data/i18n/ml_IN.yaml Normal file

File diff suppressed because it is too large Load Diff

1384
answer-data/i18n/nl_NL.yaml Normal file

File diff suppressed because it is too large Load Diff

1385
answer-data/i18n/no_NO.yaml Normal file

File diff suppressed because it is too large Load Diff

2319
answer-data/i18n/pl_PL.yaml Normal file

File diff suppressed because it is too large Load Diff

1381
answer-data/i18n/pt_BR.yaml Normal file

File diff suppressed because it is too large Load Diff

2319
answer-data/i18n/pt_PT.yaml Normal file

File diff suppressed because it is too large Load Diff

2319
answer-data/i18n/ro_RO.yaml Normal file

File diff suppressed because it is too large Load Diff

2319
answer-data/i18n/ru_RU.yaml Normal file

File diff suppressed because it is too large Load Diff

2319
answer-data/i18n/sk_SK.yaml Normal file

File diff suppressed because it is too large Load Diff

1371
answer-data/i18n/sq_AL.yaml Normal file

File diff suppressed because it is too large Load Diff

1384
answer-data/i18n/sr_SP.yaml Normal file

File diff suppressed because it is too large Load Diff

2319
answer-data/i18n/sv_SE.yaml Normal file

File diff suppressed because it is too large Load Diff

2319
answer-data/i18n/te_IN.yaml Normal file

File diff suppressed because it is too large Load Diff

2319
answer-data/i18n/tr_TR.yaml Normal file

File diff suppressed because it is too large Load Diff

2319
answer-data/i18n/uk_UA.yaml Normal file

File diff suppressed because it is too large Load Diff

2319
answer-data/i18n/vi_VN.yaml Normal file

File diff suppressed because it is too large Load Diff

2451
answer-data/i18n/zh_CN.yaml Normal file

File diff suppressed because it is too large Load Diff

2319
answer-data/i18n/zh_TW.yaml Normal file

File diff suppressed because it is too large Load Diff

144
apps.md Normal file
View File

@ -0,0 +1,144 @@
# Changemaker V5 - Apps & Services Documentation
This document provides an overview of all the applications and services included in the Changemaker V5 productivity suite, along with links to their documentation.
## Dashboard
### Homepage
- **Description**: Main dashboard for Changemaker V5
- **Documentation**: [Homepage Docs](https://gethomepage.dev/)
- **Local Access**: http://localhost:3010/
- **Details**: Homepage serves as your central command center, providing a unified dashboard to access all Changemaker services from one place. It features customizable layouts, service status monitoring, and bookmarks to frequently used pages, eliminating the need to remember numerous URLs.
## Essential Tools
### Code Server
- **Description**: Visual Studio Code in the browser
- **Documentation**: [Code Server Docs](https://coder.com/docs/code-server)
- **Local Access**: http://localhost:8888/
- **Details**: Code Server brings the power of VS Code to your browser, allowing you to develop and edit code from any device without local installation. This makes it perfect for quick edits to website content, fixing formatting issues, or developing from tablets or borrowed computers. The familiar VS Code interface includes extensions, syntax highlighting, and Git integration.
### Flatnotes
- **Description**: Simple note-taking app - connected directly to blog
- **Documentation**: [Flatnotes Docs](https://github.com/Dullage/Flatnotes)
- **Local Access**: http://localhost:8089/
- **Details**: Flatnotes offers distraction-free, markdown-based note-taking with automatic saving and powerful search. Perfect for capturing ideas that can be directly published to your blog without reformatting. Use it for drafting newsletters, documenting processes, or maintaining a knowledge base that's both private and publishable.
### Listmonk
- **Description**: Self-hosted newsletter and mailing list manager
- **Documentation**: [Listmonk Docs](https://listmonk.app/docs/)
- **Local Access**: http://localhost:9000/
- **Details**: Listmonk provides complete control over your email campaigns without subscription fees or content restrictions. Create segmented lists, design professional newsletters, track engagement metrics, and manage opt-ins/unsubscribes—all while keeping your audience data private. Perfect for consistent communication with supporters without the censorship risks or costs of commercial platforms.
### NocoDB
- **Description**: Open Source Airtable Alternative
- **Documentation**: [NocoDB Docs](https://docs.nocodb.com/)
- **Local Access**: http://localhost:8090/
- **Details**: NocoDB transforms any database into a smart spreadsheet with advanced features like forms, views, and automations. Use it to create volunteer signup systems, event management databases, or campaign tracking tools without subscription costs. Its familiar spreadsheet interface makes it accessible to non-technical users while providing the power of a relational database.
## Content Creation
### MkDocs - Material Theme
- **Description**: Static site generator and documentation builder
- **Documentation**: [MkDocs Docs](https://www.mkdocs.org/)
- **Local Access**: http://localhost:4000/
- **Details**: MkDocs with Material theme transforms simple markdown files into beautiful, professional documentation sites. Ideal for creating campaign websites, project documentation, or public-facing content that loads quickly and ranks well in search engines. The Material theme adds responsive design, dark mode, and advanced navigation features.
### Excalidraw
- **Description**: Virtual collaborative whiteboard for sketching and drawing
- **Documentation**: [Excalidraw Docs](https://github.com/excalidraw/excalidraw)
- **Local Access**: http://localhost:3333/
- **Details**: Excalidraw provides a virtual whiteboard for creating diagrams, flowcharts, or sketches with a hand-drawn feel. It's excellent for visual brainstorming, planning project workflows, or mapping out campaign strategies. Multiple people can collaborate in real-time, making it ideal for remote team planning sessions.
### Gitea
- **Description**: Lightweight self-hosted Git service
- **Documentation**: [Gitea Docs](https://docs.gitea.io/)
- **Local Access**: http://localhost:3030/
- **Details**: Gitea provides a complete code and document version control system similar to GitHub but fully under your control. Use it to track changes to campaign materials, collaborate on content development, manage website code, or maintain configuration files with full revision history. Multiple contributors can work together without overwriting each other's changes.
### OpenWebUI
- **Description**: Web interface for Ollama
- **Documentation**: [OpenWebUI Docs](https://docs.openwebui.com/)
- **Local Access**: http://localhost:3005/
- **Details**: OpenWebUI provides a user-friendly chat interface for interacting with your Ollama AI models. This makes AI accessible to non-technical team members for tasks like drafting responses, generating creative content, or researching topics. The familiar chat format allows anyone to leverage AI assistance without needing to understand the underlying technology.
## Community & Data
### Monica CRM
- **Description**: Personal relationship management system
- **Documentation**: [Monica Docs](https://www.monicahq.com/docs)
- **Local Access**: http://localhost:8085/
- **Details**: Monica CRM helps you maintain meaningful relationships by tracking interactions, important dates, and personal details about contacts. It's perfect for community organizers to remember conversation contexts, follow up appropriately, and nurture connections with supporters. Unlike corporate CRMs, Monica focuses on the human aspects of relationships rather than just sales metrics.
### Answer
- **Description**: Q&A platform for teams
- **Documentation**: [Answer Docs](https://answer.dev/docs)
- **Local Access**: http://localhost:9080/
- **Details**: Answer creates a knowledge-sharing community where team members or supporters can ask questions, provide solutions, and vote on the best responses. It builds an organized, searchable knowledge base that grows over time. Use it for internal team support, public FAQs, or gathering community input on initiatives while keeping valuable information accessible rather than buried in email threads.
### Ferdium
- **Description**: All-in-one messaging application
- **Documentation**: [Ferdium Docs](https://ferdium.org/help)
- **Local Access**: http://localhost:3002/
- **Details**: Ferdium consolidates all your communication platforms (Slack, Discord, WhatsApp, Telegram, etc.) into a single interface. This allows you to monitor and respond across channels without constantly switching applications. Perfect for community managers who need to maintain presence across multiple platforms without missing messages or getting overwhelmed.
### Rocket.Chat
- **Description**: Team collaboration platform with chat, channels, and video conferencing
- **Documentation**: [Rocket.Chat Docs](https://docs.rocket.chat/)
- **Local Access**: http://localhost:3004/
- **Details**: Rocket.Chat provides a complete communication platform for your team or community. Features include real-time chat, channels, direct messaging, file sharing, video calls, and integrations with other services. It's perfect for creating private discussion spaces, coordinating campaigns, or building community engagement. Unlike commercial platforms, you maintain full data sovereignty and control over user privacy.
## Development
### Ollama
- **Description**: Local AI model server for running large language models
- **Documentation**: [Ollama Docs](https://ollama.ai/docs)
- **Local Access**: http://localhost:11435/
- **Details**: Ollama runs powerful AI language models locally on your server, providing AI capabilities without sending sensitive data to third-party services. Use it for content generation, research assistance, or data analysis with complete privacy. Models run on your hardware, giving you full control over what AI can access and ensuring your information stays confidential.
### Portainer
- **Description**: Docker container management UI
- **Documentation**: [Portainer Docs](https://docs.portainer.io/)
- **Local Access**: https://localhost:9443/
- **Details**: Portainer simplifies Docker management with a visual interface for controlling containers, images, networks, and volumes. Instead of complex command-line operations, you can start/stop services, view logs, and manage resources through an intuitive UI, making system maintenance accessible to non-technical users.
### Mini-QR
- **Description**: QR Code Generator
- **Documentation**: [Mini-QR Docs](https://github.com/xbzbing/mini-qr)
- **Local Access**: http://localhost:8081/
- **Details**: Mini-QR enables you to quickly generate customizable QR codes for any URL, text, or contact information. Perfect for campaign materials, business cards, or event signage. Create codes that link to your digital materials without relying on third-party services that may track usage or expire.
### ConvertX
- **Description**: Self-hosted file conversion tool
- **Documentation**: [ConvertX GitHub](https://github.com/c4illin/convertx)
- **Local Access**: http://localhost:3100/
- **Details**: ConvertX provides a simple web interface for converting files between different formats. It supports a wide range of file types including documents, images, audio, and video. This enables you to maintain full control over your file conversions without relying on potentially insecure third-party services. Perfect for converting documents for campaigns, optimizing images for web use, or preparing media files for different platforms.
### n8n
- **Description**: Workflow automation platform
- **Documentation**: [n8n Docs](https://docs.n8n.io/)
- **Local Access**: http://localhost:5678/
- **Details**: n8n automates repetitive tasks by connecting your applications and services with visual workflows. You can create automations like sending welcome emails to new supporters, posting social media updates across platforms, or synchronizing contacts between databases—all without coding. This saves hours of manual work and ensures consistent follow-through on processes.
## Remote Access
When configured with Cloudflare Tunnels, you can access these services remotely at:
- Homepage: https://homepage.yourdomain.com
- Excalidraw: https://excalidraw.yourdomain.com
- Listmonk: https://listmonk.yourdomain.com
- Monica CRM: https://monica.yourdomain.com
- MkDocs: https://yourdomain.com
- Flatnotes: https://flatnotes.yourdomain.com
- Code Server: https://code-server.yourdomain.com
- Ollama: https://ollama.yourdomain.com
- OpenWebUI: https://open-web-ui.yourdomain.com
- Gitea: https://gitea.yourdomain.com
- Portainer: https://portainer.yourdomain.com
- Mini QR: https://mini-qr.yourdomain.com
- Ferdium: https://ferdium.yourdomain.com
- Answer: https://answer.yourdomain.com
- NocoDB: https://nocodb.yourdomain.com
- n8n: https://n8n.yourdomain.com
- ConvertX: https://convertx.yourdomain.com
- Rocket.Chat: https://rocket.yourdomain.com

0
assets/icons/.gitkeep Normal file
View File

BIN
assets/images/background.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 962 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

BIN
assets/images/homepage.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 851 KiB

0
assets/uploads/.gitkeep Normal file
View File

61
code-server-mkdocs.md Normal file
View File

@ -0,0 +1,61 @@
# MkDocs in Code-Server
This setup allows you to edit and manage your MkDocs site directly within the Code-Server web IDE.
## Available Commands
The MkDocs-Material package has been installed in a virtual environment with all required dependencies, including imaging support for the social plugin. You can use the following commands in the terminal inside code-server:
### Basic usage
```bash
# Run mkdocs commands directly
mkdocs --help
mkdocs build
mkdocs serve --dev-addr=0.0.0.0:8000
# Or use the convenience script that automatically changes to the mkdocs directory
run-mkdocs --help
run-mkdocs build
run-mkdocs serve --dev-addr=0.0.0.0:8000
```
### Installed MkDocs Extensions
The following MkDocs plugins and extensions are pre-installed:
- `mkdocs-material` (with imaging support)
- `mkdocs-minify-plugin`
- `mkdocs-git-revision-date-localized-plugin`
- `mkdocs-glightbox`
- `mkdocs-redirects`
### Installing Additional Plugins
To install additional MkDocs plugins or dependencies:
```bash
# Install additional MkDocs plugins
pip install <plugin-name>
# For example, to install another plugin
pip install mkdocs-awesome-pages-plugin
```
## Folder Structure
- `/home/coder/mkdocs` - Your MkDocs project directory (shared with the mkdocs container)
- `/home/coder/.venv/mkdocs/bin` - Contains the Python virtual environment with mkdocs
- `/home/coder/.local/bin` - Contains the run-mkdocs convenience script
## Tips
1. When running `mkdocs serve` inside code-server, use `--dev-addr=0.0.0.0:8000` to make it accessible.
2. The mkdocs container is still available and running in parallel if needed.
3. You can use the VS Code file explorer to easily navigate and edit your MkDocs files.
4. Use the `Code-OSS Markdown Preview` feature to preview your markdown files as you edit them.
## Tips
1. When running `mkdocs serve` inside code-server, use `--dev-addr=0.0.0.0:8000` to make it accessible.
2. The mkdocs container is still available and running in parallel if needed.
3. You can use the VS Code file explorer to easily navigate and edit your MkDocs files.

3
config.md Normal file
View File

@ -0,0 +1,3 @@
# Configuring Changemaker
The following is a configuration guide for Changemaker.

442
config.sh Executable file
View File

@ -0,0 +1,442 @@
#!/bin/bash
cat << "EOF"
██████╗██╗ ██╗ █████╗ ███╗ ██╗ ██████╗ ███████╗
██╔════╝██║ ██║██╔══██╗████╗ ██║██╔════╝ ██╔════╝
██║ ███████║███████║██╔██╗ ██║██║ ███╗█████╗
██║ ██╔══██║██╔══██║██║╚██╗██║██║ ██║██╔══╝
╚██████╗██║ ██║██║ ██║██║ ╚████║╚██████╔╝███████╗
╚═════╝╚═╝ ╚═╝╚═╝ ╚═╝╚═╝ ╚═══╝ ╚═════╝ ╚══════╝
███╗ ███╗ █████╗ ██╗ ██╗███████╗██████╗
████╗ ████║██╔══██╗██║ ██╔╝██╔════╝██╔══██╗
██╔████╔██║███████║█████╔╝ █████╗ ██████╔╝
██║╚██╔╝██║██╔══██║██╔═██╗ ██╔══╝ ██╔══██╗
██║ ╚═╝ ██║██║ ██║██║ ██╗███████╗██║ ██║
╚═╝ ╚═╝╚═╝ ╚═╝╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝
Configuration Wizard
EOF
# Get the absolute path of the script directory
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
ENV_FILE="$SCRIPT_DIR/.env"
echo "Looking for .env file at: $ENV_FILE"
# Check if .env file exists
if [ ! -f "$ENV_FILE" ]; then
echo "Error: .env file not found at $ENV_FILE"
echo "Creating a backup plan - searching for .env in current directory..."
if [ -f ".env" ]; then
ENV_FILE=".env"
echo "Found .env in current directory. Using: $ENV_FILE"
else
echo "Still no .env file found. Please make sure the .env file exists."
exit 1
fi
fi
# Function to create a timestamped backup of the .env file
backup_env_file() {
local timestamp=$(date +"%Y%m%d_%H%M%S")
local backup_file="$ENV_FILE.backup_$timestamp"
echo "Creating backup of current .env file to: $backup_file"
if cp "$ENV_FILE" "$backup_file"; then
echo "Backup created successfully!"
return 0
else
echo "Failed to create backup file. Proceeding with caution..."
return 1
fi
}
# Create a backup of the current .env file before making any changes
backup_env_file
# Function to generate a random secure password
generate_password() {
local length=${1:-16}
openssl rand -base64 48 | tr -dc 'a-zA-Z0-9!@#$%^&*()-_=+' | head -c "$length"
}
# Function to generate a base64 encoded key for Monica
generate_base64_key() {
local length=${1:-32}
local key=$(openssl rand -base64 48 | tr -dc 'a-zA-Z0-9!@#$%^&*()-_=+' | head -c "$length")
echo "base64:$(echo -n "$key" | base64)"
}
# Function to safely update environment variables in .env file
update_env_var() {
local key=$1
local value=$2
local escaped_value=$(echo "$value" | sed 's/[\/&]/\\&/g')
# Make a temporary backup of the .env file before modification
# Adding "_tmp" to distinguish from the main backup
cp "$ENV_FILE" "$ENV_FILE.bak_tmp"
if grep -q "^$key=" "$ENV_FILE"; then
# Use perl instead of sed for better handling of paths with spaces
perl -i -pe "s/^$key=.*/$key=$escaped_value/" "$ENV_FILE"
echo "Updated $key in .env file"
else
echo "$key=$escaped_value" >> "$ENV_FILE"
echo "Added $key to .env file"
fi
# Check if update was successful
if ! grep -q "^$key=$escaped_value" "$ENV_FILE"; then
echo "Warning: Failed to update $key in .env file"
echo "Restoring from backup..."
cp "$ENV_FILE.bak_tmp" "$ENV_FILE"
echo "Will try alternative method..."
# Alternative update method
local temp_file=$(mktemp)
if grep -q "^$key=" "$ENV_FILE"; then
while IFS= read -r line; do
if [[ $line =~ ^$key= ]]; then
echo "$key=$value" >> "$temp_file"
else
echo "$line" >> "$temp_file"
fi
done < "$ENV_FILE"
else
cat "$ENV_FILE" > "$temp_file"
echo "$key=$value" >> "$temp_file"
fi
mv "$temp_file" "$ENV_FILE"
fi
# Remove the temporary backup file after successful update
rm -f "$ENV_FILE.bak_tmp"
}
echo -e "\n\nWelcome to Changemaker Config!\n"
echo "This script will help you configure your Changemaker instance."
echo "Please provide the following information:"
# Domain configuration
read -p "Enter your domain name (without protocol, e.g., example.com): " domain_name
if [ -z "$domain_name" ]; then
echo "Domain name cannot be empty. Using default: changeme.org"
domain_name="changeme.org"
fi
echo -e "\nUpdating domain settings in .env file at: $ENV_FILE"
# Update main domain settings
update_env_var "DOMAIN" "$domain_name"
update_env_var "BASE_DOMAIN" "https://$domain_name"
# Update Listmonk hostname
update_env_var "LISTMONK_HOSTNAME" "listmonk.$domain_name"
# Update Gitea settings
update_env_var "GITEA_ROOT_URL" "https://gitea.$domain_name"
update_env_var "GITEA_DOMAIN" "gitea.$domain_name"
# Update Excalidraw settings
update_env_var "EXCALIDRAW_PUBLIC_URL" "https://excalidraw.$domain_name"
update_env_var "EXCALIDRAW_PUBLIC_SOCKET_URL" "https://excalidraw.$domain_name"
# Update OpenWebUI settings
echo -e "\nConfiguring OpenWebUI..."
update_env_var "OPEN_WEBUI_PORT" "3005"
update_env_var "OPEN_WEBUI_URL" "https://open-webui.$domain_name"
echo -e "Domain settings have been updated successfully!\n"
# Listmonk Admin Credentials configuration
echo -e "\n---- Listmonk Admin Credentials ----"
read -p "Enter Listmonk admin username [default: admin]: " listmonk_user
read -sp "Enter Listmonk admin password [default: strongpassword]: " listmonk_password
echo # Add new line after password input
if [ -z "$listmonk_user" ]; then
echo "Using default Listmonk admin username: admin"
listmonk_user="admin"
fi
if [ -z "$listmonk_password" ]; then
echo "Using default Listmonk admin password"
listmonk_password="strongpassword"
fi
# Update Listmonk credentials
update_env_var "LISTMONK_ADMIN_USER" "$listmonk_user"
update_env_var "LISTMONK_ADMIN_PASSWORD" "$listmonk_password"
echo "Listmonk admin credentials updated."
# Flatnotes User Credentials configuration
echo -e "\n---- Flatnotes User Credentials ----"
read -p "Enter Flatnotes username [default: user]: " flatnotes_user
read -sp "Enter Flatnotes password [default: changeMe!]: " flatnotes_password
echo # Add new line after password input
if [ -z "$flatnotes_user" ]; then
echo "Using default Flatnotes username: user"
flatnotes_user="user"
fi
if [ -z "$flatnotes_password" ]; then
echo "Using default Flatnotes password"
flatnotes_password="changeMe!"
fi
# Update Flatnotes credentials
update_env_var "FLATNOTES_USERNAME" "$flatnotes_user"
update_env_var "FLATNOTES_PASSWORD" "$flatnotes_password"
echo "Flatnotes user credentials updated."
# N8N User Credentials configuration
echo -e "\n---- N8N Admin Credentials ----"
read -p "Enter N8N admin email [default: admin@example.com]: " n8n_email
read -sp "Enter N8N admin password [default: changeMe]: " n8n_password
echo # Add new line after password input
if [ -z "$n8n_email" ]; then
echo "Using default N8N admin email: admin@example.com"
n8n_email="admin@example.com"
fi
if [ -z "$n8n_password" ]; then
echo "Using default N8N admin password"
n8n_password="changeMe"
fi
# Update N8N host and other settings
update_env_var "N8N_HOST" "n8n.$domain_name"
update_env_var "N8N_USER_EMAIL" "$n8n_email"
update_env_var "N8N_USER_PASSWORD" "$n8n_password"
update_env_var "GENERIC_TIMEZONE" "UTC"
echo "N8N admin credentials updated."
# Rocket.Chat Configuration
echo -e "\n---- Rocket.Chat Configuration ----"
read -p "Enter Rocket.Chat URL (default: https://rocket.$domain_name): " rocketchat_url
read -p "Enter Rocket.Chat port [default: 3004]: " rocketchat_port
read -p "Enable production mode for Rocket.Chat? [Y/n]: " rocketchat_production
if [ -z "$rocketchat_url" ]; then
echo "Using default Rocket.Chat URL: https://rocket.$domain_name"
rocketchat_url="https://rocket.$domain_name"
fi
if [ -z "$rocketchat_port" ]; then
echo "Using default Rocket.Chat port: 3004"
rocketchat_port="3004"
fi
rocketchat_environment="changemaker"
if [[ "$rocketchat_production" =~ ^[Yy]$ ]] || [ -z "$rocketchat_production" ]; then
echo "Enabling production mode for Rocket.Chat"
rocketchat_environment="production"
fi
# Update Rocket.Chat settings
update_env_var "ROCKETCHAT_PORT" "$rocketchat_port"
update_env_var "ROCKETCHAT_CONTAINER_PORT" "3000"
update_env_var "ROCKETCHAT_ROOT_URL" "$rocketchat_url"
update_env_var "ROCKETCHAT_DEPLOYMENT_ENVIRONMENT" "$rocketchat_environment"
echo "Rocket.Chat configuration updated."
# Cloudflare Credentials Configuration
echo -e "\n---- Cloudflare Credentials Configuration ----"
echo "Please enter your Cloudflare credentials for DNS and tunnel management."
read -p "Enter Cloudflare authentication email: " cf_auth_email
read -p "Enter Cloudflare API token: " cf_api_token
read -p "Enter Cloudflare Zone ID: " cf_zone_id
read -p "Enter Cloudflare Tunnel ID: " cf_tunnel_id
if [ -z "$cf_auth_email" ]; then
echo "Warning: Cloudflare authentication email is empty. Some features may not work correctly."
fi
if [ -z "$cf_api_token" ]; then
echo "Warning: Cloudflare API token is empty. Some features may not work correctly."
fi
if [ -z "$cf_zone_id" ]; then
echo "Warning: Cloudflare Zone ID is empty. Some features may not work correctly."
fi
if [ -z "$cf_tunnel_id" ]; then
echo "Warning: Cloudflare Tunnel ID is empty. Some features may not work correctly."
fi
# Update Cloudflare settings
update_env_var "CF_AUTH_EMAIL" "$cf_auth_email"
update_env_var "CF_API_TOKEN" "$cf_api_token"
update_env_var "CF_ZONE_ID" "$cf_zone_id"
update_env_var "CF_TUNNEL_ID" "$cf_tunnel_id"
update_env_var "CF_DOMAIN" "$domain_name"
echo "Cloudflare credentials have been updated."
echo -e "\n---- Generating Random Strong Passwords ----"
echo "Generating and updating passwords for all other services..."
# Generate and update Monica app key
monica_app_key=$(generate_base64_key 32)
update_env_var "MONICA_APP_KEY" "$monica_app_key"
# Generate and update Monica passwords
monica_db_password=$(generate_password 20)
update_env_var "MONICA_DB_PASSWORD" "$monica_db_password"
update_env_var "MONICA_MYSQL_PASSWORD" "$monica_db_password"
# Generate and update Flatnotes secret key
flatnotes_secret_key=$(generate_password 32)
update_env_var "FLATNOTES_SECRET_KEY" "$flatnotes_secret_key"
# Generate and update Gitea passwords
gitea_db_password=$(generate_password 24)
gitea_root_password=$(generate_password 24)
update_env_var "GITEA_DB_PASSWD" "$gitea_db_password"
update_env_var "GITEA_DB_ROOT_PASSWORD" "$gitea_root_password"
# Generate and update NocoDB JWT secret and database password
nocodb_jwt_secret=$(generate_password 32)
update_env_var "NOCODB_JWT_SECRET" "$nocodb_jwt_secret"
nocodb_db_password=$(generate_password 20)
update_env_var "NOCODB_DB_PASSWORD" "$nocodb_db_password"
# Generate and update n8n encryption key and default admin password
n8n_encryption_key=$(generate_password 32)
update_env_var "N8N_ENCRYPTION_KEY" "$n8n_encryption_key"
# Generate and update ConvertX JWT secret
convertx_jwt_secret=$(generate_password 48)
update_env_var "CONVERTX_JWT_SECRET" "$convertx_jwt_secret"
echo "All service passwords have been updated with secure random strings."
echo -e "\nAll settings have been configured successfully!"
echo "Your Changemaker instance is now ready with the following:"
echo "- Domain: $domain_name"
echo "- Listmonk Admin: $listmonk_user"
echo "- Flatnotes User: $flatnotes_user"
echo "- N8N Admin Email: $n8n_email"
echo "- All other service passwords have been randomized for security"
echo -e "\nNote: The randomized passwords are stored in your .env file at: $ENV_FILE"
echo -e "A backup of your original .env file was created before modifications."
# Add a new function to write the complete .env file
write_new_env_file() {
local timestamp=$(date +"%Y%m%d_%H%M%S")
local backup_file="$ENV_FILE.backup_$timestamp"
echo "Creating final backup of the current .env file to: $backup_file"
cp "$ENV_FILE" "$backup_file"
echo "Creating new .env file with all updated settings..."
# Get all variables from the current .env file
local temp_env=$(mktemp)
grep -v "^#" "$ENV_FILE" | grep "=" > "$temp_env"
# Create the new .env file with header
cat > "$ENV_FILE.new" << EOL
# Never share this file publicly. It contains sensitive information.
# This file is used to configure various applications and services.
# Generated by Changemaker Config Wizard on $(date)
EOL
# Add all sections with their variables
echo "# Domain Configuration" >> "$ENV_FILE.new"
grep -E "^DOMAIN=|^BASE_DOMAIN=" "$temp_env" >> "$ENV_FILE.new"
echo "" >> "$ENV_FILE.new"
echo "# Listmonk Configuration" >> "$ENV_FILE.new"
grep -E "^LISTMONK_" "$temp_env" >> "$ENV_FILE.new"
echo "" >> "$ENV_FILE.new"
echo "# Database Credentials" >> "$ENV_FILE.new"
grep -E "^POSTGRES_" "$temp_env" >> "$ENV_FILE.new"
echo "" >> "$ENV_FILE.new"
echo "# Monica CRM Configuration" >> "$ENV_FILE.new"
grep -E "^MONICA_" "$temp_env" >> "$ENV_FILE.new"
echo "" >> "$ENV_FILE.new"
echo "# MkDocs Configuration" >> "$ENV_FILE.new"
grep -E "^USER_ID=|^GROUP_ID=|^MKDOCS_" "$temp_env" >> "$ENV_FILE.new"
echo "" >> "$ENV_FILE.new"
echo "# Flatnotes Configuration" >> "$ENV_FILE.new"
grep -E "^FLATNOTES_" "$temp_env" >> "$ENV_FILE.new"
echo "" >> "$ENV_FILE.new"
echo "# Gitea Configuration" >> "$ENV_FILE.new"
grep -E "^GITEA_" "$temp_env" >> "$ENV_FILE.new"
echo "" >> "$ENV_FILE.new"
echo "# Apache Answer Configuration" >> "$ENV_FILE.new"
grep -E "^ANSWER_" "$temp_env" >> "$ENV_FILE.new"
echo "" >> "$ENV_FILE.new"
echo "# Excalidraw Configuration" >> "$ENV_FILE.new"
grep -E "^EXCALIDRAW_" "$temp_env" >> "$ENV_FILE.new"
echo "" >> "$ENV_FILE.new"
echo "# Code Server Configuration" >> "$ENV_FILE.new"
grep -E "^CODE_SERVER_|^USER_NAME=" "$temp_env" >> "$ENV_FILE.new"
echo "" >> "$ENV_FILE.new"
echo "# Cloudflare Credentials" >> "$ENV_FILE.new"
grep -E "^CF_" "$temp_env" >> "$ENV_FILE.new"
echo "" >> "$ENV_FILE.new"
echo "# NocoDB Configuration" >> "$ENV_FILE.new"
grep -E "^NOCODB_" "$temp_env" >> "$ENV_FILE.new"
echo "" >> "$ENV_FILE.new"
echo "# OpenWebUI Configuration" >> "$ENV_FILE.new"
grep -E "^OPEN_WEBUI_" "$temp_env" >> "$ENV_FILE.new"
echo "" >> "$ENV_FILE.new"
echo "# N8N Configuration" >> "$ENV_FILE.new"
grep -E "^N8N_|^GENERIC_TIMEZONE=" "$temp_env" >> "$ENV_FILE.new"
echo "" >> "$ENV_FILE.new"
echo "# ConvertX Configuration" >> "$ENV_FILE.new"
grep -E "^CONVERTX_" "$temp_env" >> "$ENV_FILE.new"
echo "" >> "$ENV_FILE.new"
echo "# Rocket.Chat Configuration" >> "$ENV_FILE.new"
grep -E "^ROCKETCHAT_" "$temp_env" >> "$ENV_FILE.new"
echo "" >> "$ENV_FILE.new"
# Any variables that didn't fit in the above categories
echo "# Additional Configuration" >> "$ENV_FILE.new"
grep -v -E "^DOMAIN=|^BASE_DOMAIN=|^LISTMONK_|^POSTGRES_|^MONICA_|^USER_ID=|^GROUP_ID=|^MKDOCS_|^FLATNOTES_|^GITEA_|^ANSWER_|^EXCALIDRAW_|^CODE_SERVER_|^USER_NAME=|^CF_|^NOCODB_|^OPEN_WEBUI_|^N8N_|^GENERIC_TIMEZONE=|^CONVERTX_|^ROCKETCHAT_" "$temp_env" >> "$ENV_FILE.new"
# Replace the current .env with the new one
mv "$ENV_FILE.new" "$ENV_FILE"
# Clean up
rm -f "$temp_env"
echo "New .env file created and applied successfully!"
}
# Finalizing the configuration by creating a clean .env file...
echo -e "\nFinalizing the configuration by creating a clean .env file..."
write_new_env_file
# Clean up any leftover temporary backup files
rm -f "$ENV_FILE.bak_tmp"
echo -e "Temporary backup files have been cleaned up."

View File

View File

View File

@ -0,0 +1,35 @@
#!/bin/bash
# Helper script to diagnose MkDocs configuration
echo "=== MkDocs and Python Information ==="
echo "Python version:"
python3 --version
echo ""
echo "MkDocs version:"
mkdocs --version
echo ""
echo "=== Installed Packages in Virtual Environment ==="
pip list
echo ""
echo "=== MkDocs Configuration ==="
if [ -f "mkdocs.yml" ]; then
echo "Contents of mkdocs.yml:"
cat mkdocs.yml
echo ""
echo "Checking plugins in mkdocs.yml:"
grep -A 10 "plugins:" mkdocs.yml
else
echo "mkdocs.yml not found in current directory"
fi
echo ""
echo "=== Testing MkDocs Build ==="
echo "Running: mkdocs build --strict"
mkdocs build --strict
echo ""
echo "=== Done ==="

0
configs/ferdium/.gitkeep Normal file
View File

65
configs/homepage/bookmarks.yaml Executable file
View File

@ -0,0 +1,65 @@
---
# For configuration options and examples, please see:
# https://gethomepage.dev/configs/bookmarks
- Essential Tools:
- Code Server:
- abbr: CS
href: https://github.com/coder/code-server
- Flatnotes:
- abbr: FN
href: https://github.com/dullage/flatnotes
- Listmonk:
- abbr: LM
href: https://listmonk.app/docs/
- NocoDB:
- abbr: NC
href: https://docs.nocodb.com/
- Content Creation:
- MkDocs:
- abbr: MD
href: https://www.mkdocs.org/
- Excalidraw:
- abbr: EX
href: https://github.com/excalidraw/excalidraw
- Gitea:
- abbr: GT
href: https://docs.gitea.com/
- OpenWebUI:
- abbr: OW
href: https://docs.openwebui.com/
- Community & Data:
- Monica CRM:
- abbr: MC
href: https://www.monicahq.com/documentation/
- Answer:
- abbr: AS
href: https://answer.apache.org/docs/
- Ferdium:
- abbr: FD
href: https://github.com/ferdium/ferdium-app
- Rocket.Chat:
- abbr: RC
href: https://docs.rocket.chat/
- Development:
- Ollama:
- abbr: OL
href: https://github.com/ollama/ollama
- Portainer:
- abbr: PT
href: https://docs.portainer.io/
- Mini-QR:
- abbr: QR
href: https://github.com/lyqht/mini-qr
- ConvertX:
- abbr: CX
href: https://github.com/c4illin/convertx
- n8n:
- abbr: N8
href: https://docs.n8n.io/
- Github:
- abbr: GH
href: https://github.com/

0
configs/homepage/custom.css Executable file
View File

0
configs/homepage/custom.js Executable file
View File

10
configs/homepage/docker.yaml Executable file
View File

@ -0,0 +1,10 @@
---
# For configuration options and examples, please see:
# https://gethomepage.dev/configs/docker/
# my-docker:
# host: 127.0.0.1
# port: 2375
# my-docker:
# socket: /var/run/docker.sock

View File

@ -0,0 +1,2 @@
---
# sample kubernetes config

1805
configs/homepage/logs/homepage.log Executable file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,79 @@
---
# For configuration options and examples, please see:
# https://gethomepage.dev/configs/services/
- Essential Tools:
- code-server:
href: https://code-server.betteredmonton.org
description: VS Code in the browser
icon: code-server
- Flatnotes:
href: https://flatnotes.betteredmonton.org
description: Note-taking app - connected directly to blog
icon: flatnotes
- Listmonk:
href: https://listmonk.betteredmonton.org
description: Newsletter & mailing list manager
icon: listmonk
- NocoDB:
href: https://nocodb.betteredmonton.org
description: Open Source Airtable Alternative
icon: mdi-database
- Content Creation:
- MkDocs:
href: https://live.betteredmonton.org
description: Website generator & documentation
icon: mkdocs
- Excalidraw:
href: https://excalidraw.betteredmonton.org
description: Collaborative drawing tool
icon: mdi-draw-pen
- Gitea:
href: https://gitea.betteredmonton.org
description: Self-hosted Git service
icon: gitea
- OpenWebUI:
href: https://open-webui.betteredmonton.org
description: UI for Ollama models
icon: mdi-robot-happy
- Community & Data:
- Monica CRM:
href: https://monica.betteredmonton.org
description: Personal CRM
icon: monica
- Answer:
href: https://answer.betteredmonton.org
description: Q&A platform for teams
icon: mdi-help-circle
- Ferdium:
href: https://ferdium.betteredmonton.org
description: All-in-one messaging app
icon: ferdium
- Rocket.Chat:
href: https://rocket.betteredmonton.org
description: Team collaboration platform
icon: mdi-rocket
- Development:
- Ollama:
href: https://ollama.betteredmonton.org
description: Local AI model server
icon: ollama
- Portainer:
href: https://portainer.betteredmonton.org
description: Docker management UI
icon: portainer
- Mini QR:
href: https://mini-qr.betteredmonton.org
description: QR Code Generator
icon: mdi-qrcode-edit
- ConvertX:
href: https://convertx.betteredmonton.org
description: File conversion tool
icon: mdi-file-sync
- n8n:
href: https://n8n.betteredmonton.org
description: Workflow automation
icon: n8n

42
configs/homepage/settings.yaml Executable file
View File

@ -0,0 +1,42 @@
---
# For configuration options and examples, please see:
# https://gethomepage.dev/configs/settings/
title: Changemaker
description: Changemaker is a self-hosted platform for political organizing, activism, and community building.
theme: dark # or light
color: purple
background:
image: /images/background.png
blur: xs # sm, "", md, xl... see https://tailwindcss.com/docs/backdrop-blur
saturate: 100 # 0, 50, 100... see https://tailwindcss.com/docs/backdrop-saturate
brightness: 75 # 0, 50, 75... see https://tailwindcss.com/docs/backdrop-brightness
opacity: 50 # 0-100
cardBlur: xl # xs, md,
headerStyle: boxed
layout:
style: columns
columns: 4
quicklaunch:
searchDescriptions: true
hideInternetSearch: true
showSearchSuggestions: true
hideVisitURL: true
provider: duckduckgo
showStats: true
bookmarks:
showCategories: true
showIcons: true
target: _blank
columns: 4
pinned:
- Essential Tools:code-server
- Content Creation:MkDocs
- Community & Data:Monica CRM
- Development:Ollama

34
configs/homepage/widgets.yaml Executable file
View File

@ -0,0 +1,34 @@
---
# For configuration options and examples, please see:
# https://gethomepage.dev/configs/info-widgets/
- resources:
cpu: true
memory: true
disk: /
- greeting:
text_size: xl
text: betteredmonton
href: https://betteredmonton.org
- datetime:
text_size: xl
format:
dateStyle: short
timeStyle: short
hour12: true
- search:
provider: duckduckgo
target: _blank
- openmeteo:
label: Edmonton # optional
latitude: 53.5461
longitude: -113.4938
timezone: America/Edmonton # optional
units: metric # or imperial
cache: 5 # Time in minutes to cache API responses, to stay within limits
format: # optional, Intl.NumberFormat options
maximumFractionDigits: 1

0
convertx-data/.gitkeep Normal file
View File

0
data/.gitkeep Normal file
View File

529
docker-compose.yml Executable file
View File

@ -0,0 +1,529 @@
services:
# Homepage App
homepage-changemaker:
image: ghcr.io/gethomepage/homepage:latest
container_name: homepage-changemaker
ports:
- 3010:3000
volumes:
- ./configs/homepage:/app/config
- ./assets/icons:/app/public/icons
- ./assets/images:/app/public/images
- /var/run/docker.sock:/var/run/docker.sock
environment:
- PUID=1000
- PGID=1000
- TZ=Etc/UTC
- HOMEPAGE_ALLOWED_HOSTS=*
restart: unless-stopped
networks:
- changemaker
# n8n - Workflow Automation Tool
n8n:
image: docker.n8n.io/n8nio/n8n
container_name: n8n-changemaker
restart: unless-stopped
ports:
- "${N8N_PORT:-5678}:5678"
environment:
- N8N_HOST=${N8N_HOST:-n8n.${DOMAIN}}
- N8N_PORT=5678
- N8N_PROTOCOL=https
- NODE_ENV=production
- WEBHOOK_URL=https://${N8N_HOST:-n8n.${DOMAIN}}/
- GENERIC_TIMEZONE=${GENERIC_TIMEZONE:-UTC}
- N8N_ENCRYPTION_KEY=${N8N_ENCRYPTION_KEY:-changeMe}
- N8N_USER_MANAGEMENT_DISABLED=false
- N8N_DEFAULT_USER_EMAIL=${N8N_USER_EMAIL:-admin@example.com}
- N8N_DEFAULT_USER_PASSWORD=${N8N_USER_PASSWORD:-changeMe}
volumes:
- n8n_data:/home/node/.n8n
- ./local-files:/files
networks:
- changemaker
# OpenWebUI - AI Chat Interface
open-webui:
image: ghcr.io/open-webui/open-webui:main
container_name: open-webui-changemaker
ports:
- "${OPEN_WEBUI_PORT:-3005}:8080"
volumes:
- open-webui:/app/backend/data
extra_hosts:
- "host.docker.internal:host-gateway"
restart: unless-stopped
networks:
- changemaker
depends_on:
- ollama
# Excalidraw services
excalidraw:
image: kiliandeca/excalidraw
container_name: excalidraw-changemaker
healthcheck:
disable: true
ports:
- "${EXCALIDRAW_PORT:-3333}:80"
environment:
BACKEND_V2_GET_URL: ${EXCALIDRAW_PUBLIC_URL:-http://localhost:3333}/api/v2/scenes/
BACKEND_V2_POST_URL: ${EXCALIDRAW_PUBLIC_URL:-http://localhost:3333}/api/v2/scenes/
LIBRARY_URL: ${EXCALIDRAW_LIBRARY_URL:-https://libraries.excalidraw.com}
LIBRARY_BACKEND: ${EXCALIDRAW_LIBRARY_BACKEND:-https://us-central1-excalidraw-room-persistence.cloudfunctions.net/libraries}
SOCKET_SERVER_URL: ${EXCALIDRAW_PUBLIC_SOCKET_URL:-http://localhost:3333}/
STORAGE_BACKEND: "http"
HTTP_STORAGE_BACKEND_URL: ${EXCALIDRAW_PUBLIC_URL:-http://localhost:3333}/api/v2
restart: unless-stopped
networks:
- changemaker
depends_on:
- excalidraw-storage-backend
- excalidraw-room
- redis-excalidraw
excalidraw-storage-backend:
image: kiliandeca/excalidraw-storage-backend
container_name: excalidraw-storage-backend-changemaker
restart: unless-stopped
environment:
STORAGE_URI: redis://redis-excalidraw:6379
networks:
- changemaker
depends_on:
- redis-excalidraw
excalidraw-room:
image: excalidraw/excalidraw-room
container_name: excalidraw-room-changemaker
restart: unless-stopped
networks:
- changemaker
redis-excalidraw:
image: redis:6.2-alpine
container_name: redis-excalidraw-changemaker
restart: unless-stopped
volumes:
- redis_excalidraw_data:/data
networks:
- changemaker
# listmonk app
listmonk-app:
image: listmonk/listmonk:latest
container_name: listmonk_app
restart: unless-stopped
ports:
- "9000:9000"
networks:
- changemaker
hostname: ${LISTMONK_HOSTNAME}
depends_on:
- listmonk-db
command: [sh, -c, "./listmonk --install --idempotent --yes --config '' && ./listmonk --upgrade --yes --config '' && ./listmonk --config ''"]
environment:
LISTMONK_app__address: 0.0.0.0:9000
LISTMONK_db__user: ${POSTGRES_USER}
LISTMONK_db__password: ${POSTGRES_PASSWORD}
LISTMONK_db__database: ${POSTGRES_DB}
LISTMONK_db__host: listmonk-db
LISTMONK_db__port: 5432
LISTMONK_db__ssl_mode: disable
LISTMONK_db__max_open: 25
LISTMONK_db__max_idle: 25
LISTMONK_db__max_lifetime: 300s
TZ: Etc/UTC
LISTMONK_ADMIN_USER: ${LISTMONK_ADMIN_USER:-}
LISTMONK_ADMIN_PASSWORD: ${LISTMONK_ADMIN_PASSWORD:-}
volumes:
- ./assets/uploads:/listmonk/uploads:rw
# Postgres database
listmonk-db:
image: postgres:17-alpine
container_name: listmonk-db
restart: unless-stopped
ports:
- "0.0.0.0:5432:5432"
networks:
- changemaker
environment:
POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
POSTGRES_DB: ${POSTGRES_DB}
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER}"]
interval: 10s
timeout: 5s
retries: 6
volumes:
- type: volume
source: listmonk-data
target: /var/lib/postgresql/data
# Monica CRM
monica-app:
image: monica
container_name: monica-app-changemaker
depends_on:
- monica-db
ports:
- 8085:80
environment:
- APP_KEY=${MONICA_APP_KEY}
- DB_HOST=monica-db
- DB_USERNAME=${MONICA_DB_USERNAME}
- DB_PASSWORD=${MONICA_DB_PASSWORD}
volumes:
- data:/var/www/html/storage
restart: unless-stopped
networks:
- changemaker
# Monica Database
monica-db:
image: mariadb:11
container_name: monica-db-changemaker
environment:
- MYSQL_RANDOM_ROOT_PASSWORD=true
- MYSQL_DATABASE=${MONICA_MYSQL_DATABASE}
- MYSQL_USER=${MONICA_MYSQL_USER}
- MYSQL_PASSWORD=${MONICA_MYSQL_PASSWORD}
volumes:
- mysql:/var/lib/mysql
restart: unless-stopped
networks:
- changemaker
# MkDocs Documentation
mkdocs:
image: squidfunk/mkdocs-material
container_name: markdown-editor-mkdocs-changemaker
volumes:
- ./mkdocs:/docs:rw
- ./assets/images:/docs/assets/images:rw
user: "${USER_ID:-1000}:${GROUP_ID:-1000}"
ports:
- "${MKDOCS_PORT:-4000}:8000"
environment:
- SITE_URL=${BASE_DOMAIN:-https://changeme.org}
command: serve --dev-addr=0.0.0.0:8000 --watch-theme --livereload
networks:
- changemaker
restart: unless-stopped
mkdocs-site-server:
image: lscr.io/linuxserver/nginx:latest
container_name: mkdocs-site-server-changemaker
environment:
- PUID=${USER_ID:-1000} # Uses USER_ID from your .env file, defaults to 1000
- PGID=${GROUP_ID:-1000} # Uses GROUP_ID from your .env file, defaults to 1000
- TZ=Etc/UTC
volumes:
- ./mkdocs/site:/config/www # Mounts your static site to Nginx's web root
ports:
- "4001:80" # Exposes Nginx's port 80 to host port 4001
restart: unless-stopped
networks:
- changemaker
# Flatnotes - Note-taking app
flatnotes:
container_name: flatnotes-changemaker
image: dullage/flatnotes:latest
environment:
PUID: ${FLATNOTES_PUID:-1000}
PGID: ${FLATNOTES_PGID:-1000}
FLATNOTES_AUTH_TYPE: ${FLATNOTES_AUTH_TYPE:-password}
FLATNOTES_USERNAME: ${FLATNOTES_USERNAME}
FLATNOTES_PASSWORD: ${FLATNOTES_PASSWORD}
FLATNOTES_SECRET_KEY: ${FLATNOTES_SECRET_KEY}
volumes:
- ./mkdocs/docs/blog/posts:/data
ports:
- "${FLATNOTES_PORT:-8080}:8080"
restart: unless-stopped
networks:
- changemaker
code-server:
build:
context: .
dockerfile: Dockerfile.code-server
container_name: code-server-changemaker
environment:
- DOCKER_USER=${USER_NAME:-coder}
- DEFAULT_WORKSPACE=/home/coder/mkdocs
user: "${USER_ID:-1000}:${GROUP_ID:-1000}"
volumes:
- ./configs/code-server/.config:/home/coder/.config
- ./configs/code-server/.local:/home/coder/.local
- ./mkdocs:/home/coder/mkdocs/
ports:
- "${CODE_SERVER_PORT:-8888}:8080"
restart: unless-stopped
networks:
- changemaker
ollama:
image: ollama/ollama
container_name: ollama-changemaker
deploy:
resources:
reservations:
devices:
- driver: nvidia
count: all
capabilities: [gpu]
volumes:
- ollama:/root/.ollama
ports:
- "11435:11434"
restart: unless-stopped
networks:
- changemaker
# Gitea - Git service
gitea-app:
image: docker.gitea.com/gitea:1.23.7
container_name: gitea_changemaker
environment:
- USER_UID=${USER_ID}
- USER_GID=${GROUP_ID}
- GITEA__database__DB_TYPE=${GITEA_DB_TYPE}
- GITEA__database__HOST=${GITEA_DB_HOST}
- GITEA__database__NAME=${GITEA_DB_NAME}
- GITEA__database__USER=${GITEA_DB_USER}
- GITEA__database__PASSWD=${GITEA_DB_PASSWD}
- GITEA__server__ROOT_URL=${GITEA_ROOT_URL}
- GITEA__server__HTTP_PORT=${GITEA_WEB_PORT}
- GITEA__server__PROTOCOL=http
- GITEA__server__DOMAIN=${GITEA_DOMAIN}
- GITEA__server__ENABLE_GZIP=true
- GITEA__server__PROXY_PROTOCOL=true
- GITEA__server__PROXY_PROXY_PROTOCOL_TLS=true
- GITEA__server__PROXY_ALLOW_SUBNET=0.0.0.0/0
restart: always
networks:
- gitea
volumes:
- gitea_data:/data
- /etc/timezone:/etc/timezone:ro
- /etc/localtime:/etc/localtime:ro
ports:
- "${GITEA_WEB_PORT}:3030"
- "${GITEA_SSH_PORT}:22"
depends_on:
- gitea-db
gitea-db:
image: mysql:8
container_name: gitea_mysql_changemaker
restart: always
environment:
- MYSQL_ROOT_PASSWORD=${GITEA_DB_ROOT_PASSWORD}
- MYSQL_USER=${GITEA_DB_USER}
- MYSQL_PASSWORD=${GITEA_DB_PASSWD}
- MYSQL_DATABASE=${GITEA_DB_NAME}
networks:
- gitea
volumes:
- mysql_data:/var/lib/mysql
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u", "${GITEA_DB_USER}", "-p${GITEA_DB_PASSWD}"]
interval: 10s
timeout: 5s
retries: 5
portainer:
image: portainer/portainer-ce:lts
container_name: portainer-changemaker
restart: always
environment:
- DISABLE_HTTP_REDIRECT=true
networks:
- changemaker
ports:
- "8005:8000"
- "9444:9443"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- portainer_data:/data
# Mini-QR - QR Code Generator
mini-qr:
image: ghcr.io/lyqht/mini-qr:latest
container_name: mini-qr
ports:
- 8081:8080
restart: unless-stopped
networks:
- changemaker
# Ferdium - Multiple messaging app client
ferdium:
image: lscr.io/linuxserver/ferdium:latest
container_name: ferdium-changemaker
security_opt:
- seccomp:unconfined #optional
environment:
- PUID=1000
- PGID=1000
- TZ=Etc/UTC
- CUSTOM_PORT=3009
- CUSTOM_HTTPS_PORT=3006
volumes:
- ./configs/ferdium:/config
ports:
- 3009:3009
- 3006:3006
shm_size: "1gb"
restart: unless-stopped
networks:
- changemaker
# Apache Answer - Q&A Platform
answer:
image: apache/answer
container_name: answer-changemaker
restart: unless-stopped
environment:
- DB_TYPE=sqlite3
- PAGINATION_PAGE_SIZE=10
- LANGUAGE=en-US
- TZ=Etc/UTC
ports:
- "${ANSWER_APP_PORT:-9080}:80"
volumes:
- ./answer-data:/data
networks:
- changemaker
# NocoDB - Open Source Airtable Alternative
nocodb:
depends_on:
root_db:
condition: service_healthy
environment:
NC_DB: "pg://root_db:5432?u=postgres&p=password&d=root_db"
image: "nocodb/nocodb:latest"
ports:
- "8090:8080"
restart: always
volumes:
- "nc_data:/usr/app/data"
networks:
- changemaker
root_db:
environment:
POSTGRES_DB: root_db
POSTGRES_PASSWORD: password
POSTGRES_USER: postgres
healthcheck:
interval: 10s
retries: 10
test: "pg_isready -U \"$$POSTGRES_USER\" -d \"$$POSTGRES_DB\""
timeout: 2s
image: postgres:16.6
restart: always
volumes:
- "db_data:/var/lib/postgresql/data"
networks:
- changemaker
# ConvertX - File Conversion Tool
convertx:
image: ghcr.io/c4illin/convertx
container_name: convertx-changemaker
restart: unless-stopped
ports:
- "${CONVERTX_PORT:-3100}:3000"
environment:
- JWT_SECRET=${CONVERTX_JWT_SECRET:-aLongAndSecretStringUsedToSignTheJSONWebToken1234}
volumes:
- ./convertx-data:/app/data
networks:
- changemaker
# Rocket.Chat - Team Chat Platform
rocketchat:
image: ${ROCKETCHAT_IMAGE:-registry.rocket.chat/rocketchat/rocket.chat}:${ROCKETCHAT_RELEASE:-latest}
container_name: rocketchat-changemaker
restart: unless-stopped
environment:
MONGO_URL: "mongodb://${ROCKETCHAT_MONGODB_HOST:-mongodb-rocketchat}:${ROCKETCHAT_MONGODB_PORT:-27017}/${ROCKETCHAT_MONGODB_DATABASE:-rocketchat}?replicaSet=${ROCKETCHAT_MONGODB_REPLICA_SET:-rs0}"
MONGO_OPLOG_URL: "mongodb://${ROCKETCHAT_MONGODB_HOST:-mongodb-rocketchat}:${ROCKETCHAT_MONGODB_PORT:-27017}/local?replicaSet=${ROCKETCHAT_MONGODB_REPLICA_SET:-rs0}"
ROOT_URL: ${ROCKETCHAT_ROOT_URL:-http://localhost:${ROCKETCHAT_PORT:-3004}}
PORT: ${ROCKETCHAT_CONTAINER_PORT:-3000}
DEPLOY_METHOD: docker
DEPLOY_PLATFORM: ${ROCKETCHAT_DEPLOYMENT_ENVIRONMENT:-changemaker}
ports:
- "${ROCKETCHAT_PORT:-3004}:${ROCKETCHAT_CONTAINER_PORT:-3000}"
depends_on:
- mongodb-rocketchat
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:${ROCKETCHAT_CONTAINER_PORT:-3000}/api/info"]
interval: 30s
timeout: 10s
retries: 5
start_period: 60s
networks:
- changemaker
# MongoDB for Rocket.Chat
mongodb-rocketchat:
image: docker.io/bitnami/mongodb:${ROCKETCHAT_MONGODB_VERSION:-6.0}
container_name: mongodb-rocketchat-changemaker
restart: unless-stopped
volumes:
- mongodb_rocketchat_data:/bitnami/mongodb
environment:
MONGODB_REPLICA_SET_MODE: primary
MONGODB_REPLICA_SET_NAME: ${ROCKETCHAT_MONGODB_REPLICA_SET:-rs0}
MONGODB_PORT_NUMBER: ${ROCKETCHAT_MONGODB_PORT:-27017}
MONGODB_INITIAL_PRIMARY_HOST: ${ROCKETCHAT_MONGODB_HOST:-mongodb-rocketchat}
MONGODB_INITIAL_PRIMARY_PORT_NUMBER: ${ROCKETCHAT_MONGODB_PORT:-27017}
MONGODB_ADVERTISED_HOSTNAME: ${ROCKETCHAT_MONGODB_HOST:-mongodb-rocketchat}
MONGODB_ENABLE_JOURNAL: ${ROCKETCHAT_MONGODB_ENABLE_JOURNAL:-true}
ALLOW_EMPTY_PASSWORD: ${ROCKETCHAT_MONGODB_ALLOW_EMPTY_PASSWORD:-yes}
networks:
- changemaker
networks:
changemaker:
driver: bridge
gitea:
external: false
volumes:
listmonk-data:
data:
name: data
mysql:
name: mysql
ollama:
gitea_data:
driver: local
mysql_data:
driver: local
portainer_data:
name: portainer_data_changemaker
redis_excalidraw_data:
driver: local
open-webui:
driver: local
notused:
nocodb_db_data:
driver: local
n8n_data:
driver: local
mongodb_rocketchat_data:
driver: local
db_data: {}
nc_data: {}

59
example.cloudflare.config.yml Executable file
View File

@ -0,0 +1,59 @@
tunnel: your-tunnel-id-here # e.g. 1234567890abcdef
credentials-file: /path/to/your/.cloudflared/your-tunnel-id.json # e.g. /home/user/.cloudflared/[insert tunnel number].json
ingress:
- hostname: homepage.betteredmonton.org
service: http://localhost:3010
- hostname: excalidraw.betteredmonton.org
service: http://localhost:3333
- hostname: listmonk.betteredmonton.org
service: http://localhost:9000
- hostname: monica.betteredmonton.org
service: http://localhost:8085
- hostname: live.betteredmonton.org
service: http://localhost:4000
- hostname: betteredmonton.org
service: http://localhost:4001
- hostname: flatnotes.betteredmonton.org
service: http://localhost:8089
- hostname: code-server.betteredmonton.org
service: http://localhost:8888
- hostname: ollama.betteredmonton.org
service: http://localhost:11435
- hostname: open-webui.betteredmonton.org
service: http://localhost:3005
- hostname: gitea.betteredmonton.org
service: http://localhost:3030
- hostname: mini-qr.betteredmonton.org
service: http://localhost:8081
- hostname: ferdium.betteredmonton.org
service: http://localhost:3009
- hostname: answer.betteredmonton.org
service: http://localhost:9080
- hostname: nocodb.betteredmonton.org
service: http://localhost:8090
- hostname: n8n.betteredmonton.org
service: http://localhost:5678
- hostname: convertx.betteredmonton.org
service: http://localhost:3100
- hostname: rocket.betteredmonton.org
service: http://localhost:3004
- service: http_status:404

0
gitea/.gitkeep Normal file
View File

0
local-files/.gitkeep Normal file
View File

43
mkdocs-check.sh Executable file
View File

@ -0,0 +1,43 @@
#!/bin/bash
# Script to verify MkDocs and its dependencies
echo "=== MkDocs Environment Check ==="
echo ""
# Check Python version
echo "Python version:"
python3 --version
echo ""
# Check MkDocs version
echo "MkDocs version:"
mkdocs --version
echo ""
# Check if cairosvg and PIL are available (needed for social cards)
echo "Checking for cairosvg and PIL (needed for social cards):"
python3 -c "import cairosvg; print('cairosvg is installed')" 2>/dev/null || echo "cairosvg is NOT installed"
python3 -c "from PIL import Image; print('PIL is installed')" 2>/dev/null || echo "PIL is NOT installed"
echo ""
# List all installed MkDocs plugins
echo "Installed MkDocs plugins:"
pip list | grep -i mkdocs
echo ""
# Check specific critical packages
echo "Checking critical dependencies:"
for pkg in cairosvg pillow pymdown-extensions pygments
do
pip show $pkg 2>/dev/null | grep "^Version:" || echo "$pkg is NOT installed"
done
echo ""
# Test MkDocs build capability
echo "Testing MkDocs build capability:"
cd ~/mkdocs
mkdocs build --dry-run 2>&1 | grep -v "INFO"
echo ""
echo "=== End of Check ==="

78
mkdocs-code-server.md Normal file
View File

@ -0,0 +1,78 @@
# MkDocs in Code-Server
This setup allows you to edit and manage your MkDocs site directly within the Code-Server web IDE.
## Available Commands
The MkDocs-Material package has been installed in a virtual environment with all recommended extras. You can use the following commands in the terminal inside code-server:
### Basic usage
```bash
# Run mkdocs commands directly
mkdocs --help
mkdocs build
mkdocs serve --dev-addr=0.0.0.0:8000
# Or use the convenience script that automatically changes to the mkdocs directory
run-mkdocs --help
run-mkdocs build
run-mkdocs serve --dev-addr=0.0.0.0:8000
```
### Advanced Features
The following MkDocs-Material features are available:
1. **Social Cards** - Automatically generate social cards for your pages
2. **PDF Export** - Create PDF versions of your documentation
3. **Mermaid Diagrams** - Create flowcharts and diagrams
4. **Blog Support** - Use the blog plugin for creating blog posts
5. **Git Integration** - Show last update date from git history
### Installing Additional Plugins
If you need to install additional plugins:
```bash
# Install additional MkDocs plugins
pip install <plugin-name>
# For example, to install a new plugin
pip install mkdocs-your-plugin-name
```
## Troubleshooting
If you encounter issues with dependencies, run the following script to check the installation:
```bash
bash /home/bunker-admin/Changemaker/mkdocs-check.sh
```
## Installed Plugins
The following plugins are pre-installed:
- mkdocs-material (with imaging, recommended, and git extras)
- mkdocs-minify-plugin
- mkdocs-git-revision-date-localized-plugin
- mkdocs-glightbox
- mkdocs-redirects
- mkdocs-awesome-pages-plugin
- mkdocs-blog-plugin
- mkdocs-rss-plugin
- mkdocs-meta-descriptions-plugin
- mkdocs-swagger-ui-tag
- mkdocs-macros-plugin
- mkdocs-material-extensions
- mkdocs-section-index
- mkdocs-table-reader-plugin
- mkdocs-pdf-export-plugin
- mkdocs-mermaid2-plugin
## Folder Structure
- `/home/coder/mkdocs` - Your MkDocs project directory (shared with the mkdocs container)
- `/home/coder/.venv/mkdocs/bin` - Contains the mkdocs executable and installed plugins
- `/home/coder/.local/bin` - Contains convenience scripts

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

Some files were not shown because too many files have changed in this diff Show More