Compare commits

...

5 Commits

Author SHA1 Message Date
Andreas Dueren
5f8238cbc2 Remove CONFIGURATION.md and DEPLOYMENT.md files
Removed documentation files and updated references:
- Deleted CONFIGURATION.md and DEPLOYMENT.md
- Updated Dockerfile to remove CONFIGURATION.md copy
- Updated start.sh to remove CONFIGURATION.md copy
- Fixed license reference back to AGPL-3.0 (Docmost's actual license)

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-07-15 13:50:52 -06:00
Andreas Dueren
a64e79e3fc Fix license reference from AGPL-3.0 to MIT
Docmost uses MIT license, not AGPL-3.0.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-07-15 13:49:40 -06:00
Andreas Dueren
e2a2665fb1 Remove obsolete files and clean up repository structure
Removed unused files:
- oidc-middleware.js (unused OIDC authentication code)
- package.json (dependencies for unused middleware)
- healthcheck.js (Cloudron uses manifest healthCheckPath instead)

Updated Dockerfile to remove healthcheck.js references.
Updated DEPLOYMENT.md to reflect current repository structure.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-07-15 13:49:09 -06:00
Andreas Dueren
fe3e9fc27e Remove personal Cloudron builder references from documentation
Cleaned up build commands to use standard `cloudron build` without
personal builder service references or tokens.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-07-15 13:46:07 -06:00
Andreas Dueren
34ef0803d8 Fix .env file parsing errors with better validation and error handling 2025-07-15 13:41:35 -06:00
8 changed files with 20 additions and 433 deletions

View File

@@ -1,127 +0,0 @@
# Docmost Cloudron Configuration
Your Docmost instance is configured with Cloudron defaults but can be customized after installation.
## Current Configuration
**Email**: Uses Cloudron's internal email server by default
**Storage**: Uses local storage in `/app/data/uploads` by default
**Database**: PostgreSQL (managed by Cloudron)
**Cache**: Redis (managed by Cloudron)
## Custom Configuration
To customize your Docmost installation, you can create a `.env` file in the app's data directory:
### 1. Access Your App's Data Directory
```bash
# SSH into your Cloudron server
cloudron exec --app docmost
# Navigate to the data directory
cd /app/data
# Copy the sample configuration
cp env.sample .env
```
### 2. Edit the Configuration
```bash
# Edit the .env file
nano .env
```
### 3. Restart the App
After making changes to the `.env` file, restart the app:
```bash
cloudron restart --app docmost
```
## Common Customizations
### Custom Email Server
To use Gmail instead of Cloudron's email server:
```bash
# In /app/data/.env
MAIL_DRIVER=smtp
SMTP_HOST=smtp.gmail.com
SMTP_PORT=587
SMTP_USERNAME=your-email@gmail.com
SMTP_PASSWORD=your-app-password
SMTP_SECURE=true
MAIL_FROM_ADDRESS=your-email@gmail.com
MAIL_FROM_NAME=Docmost
```
### S3 Storage
To use Amazon S3 or compatible storage:
```bash
# In /app/data/.env
STORAGE_DRIVER=s3
AWS_S3_ACCESS_KEY_ID=your-access-key
AWS_S3_SECRET_ACCESS_KEY=your-secret-key
AWS_S3_REGION=us-east-1
AWS_S3_BUCKET=your-bucket-name
AWS_S3_ENDPOINT=https://s3.amazonaws.com
```
### File Upload Limits
To increase file upload limits:
```bash
# In /app/data/.env
FILE_UPLOAD_SIZE_LIMIT=100MB
FILE_IMPORT_SIZE_LIMIT=100MB
```
### Custom Draw.io Server
To use a self-hosted draw.io server:
```bash
# In /app/data/.env
DRAWIO_URL=https://your-drawio-server.com
```
## Available Environment Variables
See the full list of available environment variables in the [Docmost documentation](https://docmost.com/docs/self-hosting/environment-variables).
## Troubleshooting
### Check Current Configuration
```bash
cloudron exec --app docmost -- env | grep -E "(MAIL|STORAGE|S3)" | sort
```
### View App Logs
```bash
cloudron logs --app docmost
```
### Reset to Defaults
To reset to Cloudron defaults, simply remove the custom .env file:
```bash
cloudron exec --app docmost -- rm -f /app/data/.env
cloudron restart --app docmost
```
## Security Notes
- The `.env` file is stored in `/app/data/` which is included in Cloudron backups
- Database and Redis credentials are managed by Cloudron and should not be changed
- Email credentials are stored in plaintext in the `.env` file
- Consider using app-specific passwords for email providers

View File

@@ -1,93 +0,0 @@
# Docmost Cloudron Package - Deployment Status
## Current Status: 🔄 In Progress
The Docmost Cloudron package has been successfully created with all required components but is experiencing a Redis URL parsing issue preventing startup.
## Package Components Created ✅
### Core Files
- **CloudronManifest.json** - Complete app configuration with all addons
- **Dockerfile** - Production build with Node.js 20 and pnpm
- **start.sh** - Initialization script with database setup
- **nginx.conf** - Reverse proxy with WebSocket support
- **supervisord.conf** - Process management configuration
- **README.md** - Comprehensive documentation
### Features Implemented
- ✅ PostgreSQL database integration
- ✅ Email notifications via Cloudron SMTP
- ✅ File storage in persistent directory
- ✅ Health checks and logging
- ✅ Production-ready build process
- ✅ WebSocket support for real-time collaboration
- ⚠️ Redis integration (currently blocked by URL parsing issue)
## Current Issue 🔧
**Problem**: Redis URL parsing incompatibility
- **Error**: `RangeError [ERR_SOCKET_BAD_PORT]: Port should be >= 0 and < 65536. Received type number (NaN)`
- **Root Cause**: Cloudron Redis URL format differs from what Docmost expects
- **Impact**: App cannot start due to Redis validation failure
## Build Information
**Latest Version**: andreasdueren/docmost-cloudron:0.1.8
**Status**: App installs and runs but returns 502 due to Redis parsing issue
### Build Commands
```bash
# Build
cloudron build --set-build-service builder.docker.due.ren \
--build-service-token e3265de06b1d0e7bb38400539012a8433a74c2c96a17955e \
--set-repository andreasdueren/docmost-cloudron --tag 0.1.8
# Install
cloudron install --location docmost.due.ren \
--image andreasdueren/docmost-cloudron:0.1.8
```
## Next Steps 🎯
1. **Debug Redis URL format** - Add logging to understand Cloudron Redis URL structure
2. **Fix URL parsing** - Implement correct Redis URL transformation
3. **Test without Redis** - Investigate if Docmost can run without Redis for basic functionality
4. **Final deployment** - Complete working package
## Repository Structure
```
docmost-cloudron/
├── CloudronManifest.json # App configuration
├── Dockerfile # Container build
├── start.sh # Startup script
├── nginx.conf # Reverse proxy
├── supervisord.conf # Process management
├── oidc-middleware.js # Authentication (future)
├── package.json # Dependencies
├── README.md # Documentation
└── DEPLOYMENT.md # This file
```
## Troubleshooting
**For Redis URL Issues:**
```bash
# Check logs
cloudron logs --app docmost.due.ren
# Shell into container
cloudron exec --app docmost.due.ren
# Check Redis URL format
echo $CLOUDRON_REDIS_URL
```
**For Build Issues:**
```bash
# Clean build
git clean -fdx
cloudron build --tag $(date +%s)
```
The package is 95% complete with all infrastructure in place. Only the Redis URL compatibility issue remains to be resolved for full functionality.

View File

@@ -24,17 +24,15 @@ RUN mkdir -p /tmp/data /app/data && \
# Copy startup scripts and configuration files # Copy startup scripts and configuration files
COPY start.sh /app/code/ COPY start.sh /app/code/
COPY healthcheck.js /app/code/
COPY nginx.conf /etc/nginx/sites-available/default COPY nginx.conf /etc/nginx/sites-available/default
COPY env.sample /app/code/env.sample COPY env.sample /app/code/env.sample
COPY CONFIGURATION.md /app/code/CONFIGURATION.md
# Override nginx global logs to prevent read-only filesystem errors # Override nginx global logs to prevent read-only filesystem errors
RUN sed -i 's|error_log /var/log/nginx/error.log;|error_log /dev/stderr;|' /etc/nginx/nginx.conf && \ RUN sed -i 's|error_log /var/log/nginx/error.log;|error_log /dev/stderr;|' /etc/nginx/nginx.conf && \
sed -i 's|access_log /var/log/nginx/access.log;|access_log /dev/stdout;|' /etc/nginx/nginx.conf sed -i 's|access_log /var/log/nginx/access.log;|access_log /dev/stdout;|' /etc/nginx/nginx.conf
# Make scripts executable # Make scripts executable
RUN chmod +x /app/code/start.sh /app/code/healthcheck.js RUN chmod +x /app/code/start.sh
# Install supervisord and netcat for process management and connectivity checks # Install supervisord and netcat for process management and connectivity checks
RUN apt-get update && \ RUN apt-get update && \

View File

@@ -28,18 +28,14 @@ Docmost is a collaborative documentation platform featuring:
2. Build the Cloudron package: 2. Build the Cloudron package:
```bash ```bash
cloudron build --set-build-service builder.docker.due.ren \ cloudron build
--build-service-token e3265de06b1d0e7bb38400539012a8433a74c2c96a17955e \
--set-repository andreasdueren/docmost-cloudron \
--tag 0.1.2
``` ```
## Installation ## Installation
1. Install the package on your Cloudron: 1. Install the package on your Cloudron:
```bash ```bash
cloudron install --location docmost.yourdomain.com \ cloudron install --location docmost
--image andreasdueren/docmost-cloudron:0.1.2
``` ```
2. After installation, access your Docmost instance at the configured domain. 2. After installation, access your Docmost instance at the configured domain.
@@ -99,15 +95,12 @@ If the build fails, try:
1. **Clean build**: 1. **Clean build**:
```bash ```bash
git clean -fdx git clean -fdx
cloudron build --set-build-service builder.docker.due.ren \ cloudron build
--build-service-token e3265de06b1d0e7bb38400539012a8433a74c2c96a17955e \
--set-repository andreasdueren/docmost-cloudron \
--tag 0.1.3
``` ```
2. **Check logs**: 2. **Check logs**:
```bash ```bash
cloudron logs --app docmost.yourdomain.com -f cloudron logs --app docmost
``` ```
### Installation Issues ### Installation Issues

View File

@@ -1,34 +0,0 @@
#!/usr/bin/env node
const http = require('http');
// Simple health check that attempts to connect to the app
const options = {
hostname: 'localhost',
port: 3001,
path: '/',
method: 'GET',
timeout: 5000
};
const req = http.request(options, (res) => {
console.log(`Health check: ${res.statusCode}`);
if (res.statusCode === 200) {
process.exit(0);
} else {
process.exit(1);
}
});
req.on('error', (err) => {
console.error('Health check failed:', err.message);
process.exit(1);
});
req.on('timeout', () => {
console.error('Health check timeout');
req.abort();
process.exit(1);
});
req.end();

View File

@@ -1,145 +0,0 @@
const express = require('express');
const jwt = require('jsonwebtoken');
const axios = require('axios');
class CloudronOIDCMiddleware {
constructor(options = {}) {
this.clientId = process.env.CLOUDRON_OIDC_CLIENT_ID;
this.clientSecret = process.env.CLOUDRON_OIDC_CLIENT_SECRET;
this.issuer = process.env.CLOUDRON_OIDC_ISSUER;
this.redirectUri = process.env.OIDC_REDIRECT_URI;
this.appOrigin = process.env.CLOUDRON_APP_ORIGIN;
}
// Middleware to check authentication
authenticate() {
return async (req, res, next) => {
try {
// Check for existing session/token
const token = req.headers.authorization?.replace('Bearer ', '') ||
req.cookies?.authToken ||
req.session?.token;
if (token && this.verifyToken(token)) {
req.user = jwt.decode(token);
return next();
}
// If no valid token, redirect to OIDC login
if (req.path.startsWith('/api/')) {
return res.status(401).json({ error: 'Authentication required' });
}
// Redirect to OIDC authorization
const authUrl = this.buildAuthUrl();
res.redirect(authUrl);
} catch (error) {
console.error('Authentication error:', error);
res.status(500).json({ error: 'Authentication failed' });
}
};
}
// Build OIDC authorization URL
buildAuthUrl() {
const params = new URLSearchParams({
response_type: 'code',
client_id: this.clientId,
redirect_uri: this.redirectUri,
scope: 'openid profile email',
state: this.generateState()
});
return `${this.issuer}/auth?${params.toString()}`;
}
// Handle OIDC callback
async handleCallback(req, res) {
try {
const { code, state } = req.query;
if (!code) {
return res.status(400).json({ error: 'Authorization code required' });
}
// Exchange code for tokens
const tokenResponse = await this.exchangeCodeForTokens(code);
const { access_token, id_token } = tokenResponse.data;
// Verify and decode the ID token
const userInfo = jwt.decode(id_token);
// Create user session
const sessionToken = this.createSessionToken(userInfo);
// Set cookie and redirect
res.cookie('authToken', sessionToken, {
httpOnly: true,
secure: true,
sameSite: 'lax',
maxAge: 30 * 24 * 60 * 60 * 1000 // 30 days
});
res.redirect('/');
} catch (error) {
console.error('OIDC callback error:', error);
res.status(500).json({ error: 'Authentication callback failed' });
}
}
// Exchange authorization code for tokens
async exchangeCodeForTokens(code) {
const params = new URLSearchParams({
grant_type: 'authorization_code',
code,
redirect_uri: this.redirectUri,
client_id: this.clientId,
client_secret: this.clientSecret
});
return axios.post(`${this.issuer}/token`, params, {
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
});
}
// Create session token
createSessionToken(userInfo) {
const payload = {
sub: userInfo.sub,
email: userInfo.email,
name: userInfo.name,
iat: Math.floor(Date.now() / 1000),
exp: Math.floor(Date.now() / 1000) + (30 * 24 * 60 * 60) // 30 days
};
return jwt.sign(payload, process.env.APP_SECRET);
}
// Verify JWT token
verifyToken(token) {
try {
const decoded = jwt.verify(token, process.env.APP_SECRET);
return decoded.exp > Math.floor(Date.now() / 1000);
} catch (error) {
return false;
}
}
// Generate random state for CSRF protection
generateState() {
return Math.random().toString(36).substring(2, 15) +
Math.random().toString(36).substring(2, 15);
}
// Logout handler
logout() {
return (req, res) => {
res.clearCookie('authToken');
res.redirect('/');
};
}
}
module.exports = CloudronOIDCMiddleware;

View File

@@ -1,14 +0,0 @@
{
"name": "docmost-cloudron",
"version": "1.0.0",
"description": "Cloudron package for Docmost",
"scripts": {
"start": "./start.sh"
},
"dependencies": {
"express": "^4.18.2",
"jsonwebtoken": "^9.0.2",
"axios": "^1.6.0",
"cookie-parser": "^1.4.6"
}
}

View File

@@ -11,12 +11,11 @@ if [ ! -d "/app/data/client-dist" ]; then
chown -R cloudron:cloudron /app/data/client-dist chown -R cloudron:cloudron /app/data/client-dist
fi fi
# Copy sample .env file and documentation for user reference # Copy sample .env file for user reference
if [ ! -f "/app/data/env.sample" ]; then if [ ! -f "/app/data/env.sample" ]; then
echo "=> Copying configuration files to /app/data/" echo "=> Copying configuration files to /app/data/"
cp /app/code/env.sample /app/data/env.sample cp /app/code/env.sample /app/data/env.sample
cp /app/code/CONFIGURATION.md /app/data/CONFIGURATION.md chown cloudron:cloudron /app/data/env.sample
chown cloudron:cloudron /app/data/env.sample /app/data/CONFIGURATION.md
fi fi
# Initialize /app/data if it's empty (first run) # Initialize /app/data if it's empty (first run)
@@ -102,9 +101,19 @@ fi
# Load custom environment variables if they exist # Load custom environment variables if they exist
if [ -f "/app/data/.env" ]; then if [ -f "/app/data/.env" ]; then
echo "=> Loading custom environment variables from /app/data/.env" echo "=> Loading custom environment variables from /app/data/.env"
set -a # automatically export all variables # Validate .env file format before sourcing
source /app/data/.env if grep -q "^[[:space:]]*[^#][^=]*=" /app/data/.env 2>/dev/null; then
set +a # stop automatically exporting set -a # automatically export all variables
if source /app/data/.env 2>/dev/null; then
echo "=> Custom .env file loaded successfully"
else
echo "=> Warning: Error loading .env file, using Cloudron defaults"
echo "=> Check /app/data/.env for syntax errors (values with spaces need quotes)"
fi
set +a # stop automatically exporting
else
echo "=> Warning: /app/data/.env appears to be empty or invalid, using Cloudron defaults"
fi
else else
echo "=> No custom .env file found, using Cloudron defaults" echo "=> No custom .env file found, using Cloudron defaults"
fi fi