Compare commits

...

15 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
Andreas Dueren
65cd9a73bb Initial commit: Docmost Cloudron package with customizable configuration 2025-07-15 13:13:03 -06:00
Andreas Dueren
49ae672cb5 Fix nginx error log and debug Redis URL format 2025-07-15 08:38:42 -06:00
Andreas Dueren
12917e3dd9 Add health check script and improve Redis debugging 2025-07-15 08:33:54 -06:00
Andreas Dueren
34c2d30c0c Implement robust Redis URL parsing and connection checking 2025-07-15 08:25:26 -06:00
Andreas Dueren
6656311f89 Debug and fix Redis URL parsing issue 2025-07-15 06:51:17 -06:00
Andreas Dueren
af2e3c687b Fix Redis requirement, nginx logging, and prisma path 2025-07-14 21:37:35 -06:00
Andreas Dueren
675c6fa1c8 Fix Redis configuration and remove Redis addon temporarily 2025-07-14 21:31:09 -06:00
Andreas Dueren
eab30de088 Fix filesystem readonly issues and pnpm path 2025-07-14 21:23:09 -06:00
Andreas Dueren
080ff206b2 Remove OIDC integration, use built-in authentication 2025-07-14 21:18:25 -06:00
Andreas Dueren
b9f183b5aa Fix manifest icon and version compatibility 2025-07-14 21:11:23 -06:00
10 changed files with 289 additions and 199 deletions

View File

@@ -5,7 +5,7 @@
"description": "Open-source collaborative wiki and documentation platform. A modern alternative to Confluence and Notion with real-time collaboration, diagram support, and multilingual capabilities.",
"tagline": "Collaborative wiki and documentation platform",
"version": "1.0.0",
"healthCheckPath": "/api/health",
"healthCheckPath": "/",
"httpPort": 3000,
"addons": {
"postgresql": {},
@@ -16,7 +16,6 @@
"manifestVersion": 2,
"website": "https://docmost.com",
"contactEmail": "support@docmost.com",
"icon": "logo.png",
"tags": [
"productivity",
"collaboration",
@@ -24,11 +23,11 @@
"wiki",
"knowledge-base"
],
"postInstallMessage": "Docmost has been installed successfully!\n\nTo get started:\n1. Access your Docmost instance at https://%s\n2. Create your first workspace and admin account\n3. Start collaborating on documentation\n\nDefault features include:\n- Real-time collaborative editing\n- Diagram support (Draw.io, Excalidraw, Mermaid)\n- Page history and permissions\n- Multilingual support\n\nFor more information, visit: https://docmost.com/docs",
"postInstallMessage": "Docmost has been installed successfully!\n\nTo get started:\n1. Access your Docmost instance at https://{{CLOUDRON_APP_DOMAIN}}\n2. Create your first workspace and admin account\n3. Start collaborating on documentation\n\nDefault configuration:\n- Email: Uses Cloudron's internal email server\n- Storage: Local storage in /app/data/uploads\n- Database: PostgreSQL (managed by Cloudron)\n- Cache: Redis (managed by Cloudron)\n\nCustomization:\nTo customize email, storage, or other settings, create /app/data/.env file:\n cloudron exec --app docmost\n cp /app/data/env.sample /app/data/.env\n nano /app/data/.env\n exit\n cloudron restart --app docmost\n\nFeatures include:\n- Real-time collaborative editing\n- Diagram support (Draw.io, Excalidraw, Mermaid)\n- Page history and permissions\n- Multilingual support\n\nFor more information, visit: https://docmost.com/docs",
"minBoxVersion": "7.0.0",
"maxBoxVersion": "8.0.0",
"maxBoxVersion": "9.0.0",
"memoryLimit": 512000000,
"optionalSso": true,
"optionalSso": false,
"mediaLinks": [
"https://docmost.com",
"https://github.com/docmost/docmost"

View File

@@ -14,22 +14,29 @@ WORKDIR /app/code
RUN git clone https://github.com/docmost/docmost.git . && \
rm -rf .git && \
pnpm install && \
pnpm build
pnpm build && \
mv apps/client/dist /app/client-dist-original && \
ln -s /app/data/client-dist apps/client/dist
# Create necessary directories
RUN mkdir -p /tmp/data /app/data && \
chown -R cloudron:cloudron /app/data /tmp/data
# Copy startup scripts
# Copy startup scripts and configuration files
COPY start.sh /app/code/
COPY nginx.conf /etc/nginx/sites-available/default
COPY env.sample /app/code/env.sample
# 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 && \
sed -i 's|access_log /var/log/nginx/access.log;|access_log /dev/stdout;|' /etc/nginx/nginx.conf
# Make scripts executable
RUN chmod +x /app/code/start.sh
# Install supervisord for process management
# Install supervisord and netcat for process management and connectivity checks
RUN apt-get update && \
apt-get install -y supervisor && \
apt-get install -y supervisor netcat-openbsd && \
rm -rf /var/lib/apt/lists/*
COPY supervisord.conf /etc/supervisor/conf.d/supervisord.conf

21
LICENSE Normal file
View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2025 Andreas Dueren
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

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

66
env.sample Normal file
View File

@@ -0,0 +1,66 @@
# Docmost Cloudron Configuration
# Copy this file to /app/data/.env and customize as needed
# Restart the app after making changes: cloudron restart --app docmost
# ======================
# EMAIL CONFIGURATION
# ======================
# By default, Docmost uses Cloudron's internal email server
# Uncomment and modify these lines to use a custom email server
# 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"
# Alternative: Use Postmark for email
# MAIL_DRIVER=postmark
# POSTMARK_TOKEN=your-postmark-token
# ======================
# STORAGE CONFIGURATION
# ======================
# By default, files are stored locally in /app/data/uploads
# Uncomment and modify these lines to use S3-compatible storage
# 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
# AWS_S3_FORCE_PATH_STYLE=false
# For other S3-compatible services (like MinIO, DigitalOcean Spaces):
# AWS_S3_ENDPOINT=https://your-minio-server.com
# AWS_S3_FORCE_PATH_STYLE=true
# ======================
# FILE UPLOAD LIMITS
# ======================
# FILE_UPLOAD_SIZE_LIMIT=50MB
# FILE_IMPORT_SIZE_LIMIT=50MB
# ======================
# APPLICATION SETTINGS
# ======================
# JWT_TOKEN_EXPIRES_IN=7d
# DRAWIO_URL=https://embed.diagrams.net
# Privacy: Disable telemetry (enabled by default)
# DISABLE_TELEMETRY=true
# ======================
# DATABASE & REDIS
# ======================
# These are managed by Cloudron and should not be changed
# DATABASE_URL=postgresql://...
# REDIS_URL=redis://...

View File

@@ -6,6 +6,17 @@ server {
index index.html;
client_max_body_size 100m;
# Create temporary directories in writable locations
client_body_temp_path /tmp/nginx_client_temp;
proxy_temp_path /tmp/nginx_proxy_temp;
fastcgi_temp_path /tmp/nginx_fastcgi_temp;
uwsgi_temp_path /tmp/nginx_uwsgi_temp;
scgi_temp_path /tmp/nginx_scgi_temp;
# Log to stdout/stderr instead of files
access_log /dev/stdout;
error_log /dev/stderr;
# Enable compression
gzip on;

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

190
start.sh
View File

@@ -4,6 +4,20 @@ set -eu
echo "=> Starting Docmost setup"
# Set up writable client dist directory
if [ ! -d "/app/data/client-dist" ]; then
echo "=> Setting up writable client dist directory"
cp -r /app/client-dist-original /app/data/client-dist
chown -R cloudron:cloudron /app/data/client-dist
fi
# Copy sample .env file for user reference
if [ ! -f "/app/data/env.sample" ]; then
echo "=> Copying configuration files to /app/data/"
cp /app/code/env.sample /app/data/env.sample
chown cloudron:cloudron /app/data/env.sample
fi
# Initialize /app/data if it's empty (first run)
if [ ! -f /app/data/.initialized ]; then
echo "=> Initializing data directory"
@@ -26,31 +40,133 @@ APP_SECRET=$(cat /app/data/app_secret)
export NODE_ENV=production
export APP_URL="${CLOUDRON_APP_ORIGIN}"
export APP_SECRET="${APP_SECRET}"
export PORT=3000
export PORT=3001
# Database configuration
export DATABASE_URL="${CLOUDRON_POSTGRESQL_URL}"
# Redis configuration
export REDIS_URL="${CLOUDRON_REDIS_URL}"
# Redis configuration - parse Cloudron format to standard format
echo "=> Configuring Redis..."
# Email configuration
export MAIL_DRIVER=smtp
export SMTP_HOST="${CLOUDRON_MAIL_SMTP_SERVER}"
export SMTP_PORT="${CLOUDRON_MAIL_SMTP_PORT}"
export SMTP_USERNAME="${CLOUDRON_MAIL_SMTP_USERNAME}"
export SMTP_PASSWORD="${CLOUDRON_MAIL_SMTP_PASSWORD}"
export MAIL_FROM_ADDRESS="${CLOUDRON_MAIL_FROM}"
# Cloudron provides Redis addon with specific environment variables
# The CLOUDRON_REDIS_URL is in format: redis://:password@host:port
# We need to ensure it's in the correct format for ioredis
# Storage configuration (using local storage)
export STORAGE_DRIVER=local
export STORAGE_LOCAL_PATH="/app/data/uploads"
# Debug: Print the original Redis URL
echo "=> Original CLOUDRON_REDIS_URL: ${CLOUDRON_REDIS_URL}"
# OIDC configuration for Cloudron authentication
export OIDC_CLIENT_ID="${CLOUDRON_OIDC_CLIENT_ID}"
export OIDC_CLIENT_SECRET="${CLOUDRON_OIDC_CLIENT_SECRET}"
export OIDC_ISSUER="${CLOUDRON_OIDC_ISSUER}"
export OIDC_REDIRECT_URI="${CLOUDRON_APP_ORIGIN}/api/v1/session/callback"
if [ -n "${CLOUDRON_REDIS_URL}" ]; then
# Parse the URL components first
# Also extract components for individual env vars
# Handle both formats: redis://default:password@host and redis://:password@host:port
if echo "$CLOUDRON_REDIS_URL" | grep -q "redis://default:"; then
# Format: redis://default:password@host
REDIS_PASSWORD=$(echo "$CLOUDRON_REDIS_URL" | sed -n 's|redis://default:\([^@]*\)@.*|\1|p')
REDIS_HOST=$(echo "$CLOUDRON_REDIS_URL" | sed -n 's|redis://default:[^@]*@\([^:/]*\).*|\1|p')
REDIS_PORT=$(echo "$CLOUDRON_REDIS_URL" | sed -n 's|redis://default:[^@]*@[^:]*:\([0-9]*\).*|\1|p')
else
# Format: redis://:password@host:port
REDIS_PASSWORD=$(echo "$CLOUDRON_REDIS_URL" | sed -n 's|redis://:\([^@]*\)@.*|\1|p')
REDIS_HOST=$(echo "$CLOUDRON_REDIS_URL" | sed -n 's|redis://[^@]*@\([^:]*\):.*|\1|p')
REDIS_PORT=$(echo "$CLOUDRON_REDIS_URL" | sed -n 's|redis://[^@]*@[^:]*:\([0-9]*\).*|\1|p')
fi
# Default port if not found
if [ -z "$REDIS_PORT" ]; then
REDIS_PORT="6379"
fi
# Export individual components for Docmost
export REDIS_HOST="${REDIS_HOST}"
export REDIS_PORT="${REDIS_PORT}"
export REDIS_PASSWORD="${REDIS_PASSWORD}"
export REDIS_DB="0"
echo "=> Redis configured: host=${REDIS_HOST}, port=${REDIS_PORT}, has password: $([ -n "$REDIS_PASSWORD" ] && echo "yes" || echo "no")"
# Reconstruct the Redis URL in the correct format for ioredis
if [ -n "$REDIS_PASSWORD" ]; then
export REDIS_URL="redis://:${REDIS_PASSWORD}@${REDIS_HOST}:${REDIS_PORT}"
else
export REDIS_URL="redis://${REDIS_HOST}:${REDIS_PORT}"
fi
echo "=> Using Redis URL: ${REDIS_URL}"
else
echo "=> Error: Redis URL not provided by Cloudron"
exit 1
fi
# Load custom environment variables if they exist
if [ -f "/app/data/.env" ]; then
echo "=> Loading custom environment variables from /app/data/.env"
# Validate .env file format before sourcing
if grep -q "^[[:space:]]*[^#][^=]*=" /app/data/.env 2>/dev/null; then
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
echo "=> No custom .env file found, using Cloudron defaults"
fi
# Email configuration - use custom settings if provided, otherwise use Cloudron defaults
export MAIL_DRIVER="${MAIL_DRIVER:-smtp}"
export SMTP_HOST="${SMTP_HOST:-${CLOUDRON_MAIL_SMTP_SERVER}}"
export SMTP_PORT="${SMTP_PORT:-${CLOUDRON_MAIL_SMTP_PORT}}"
export SMTP_USERNAME="${SMTP_USERNAME:-${CLOUDRON_MAIL_SMTP_USERNAME}}"
export SMTP_PASSWORD="${SMTP_PASSWORD:-${CLOUDRON_MAIL_SMTP_PASSWORD}}"
export SMTP_SECURE="${SMTP_SECURE:-false}"
export MAIL_FROM_ADDRESS="${MAIL_FROM_ADDRESS:-${CLOUDRON_MAIL_FROM}}"
export MAIL_FROM_NAME="${MAIL_FROM_NAME:-Docmost}"
# Storage configuration - use custom settings if provided, otherwise use local storage
export STORAGE_DRIVER="${STORAGE_DRIVER:-local}"
export STORAGE_LOCAL_PATH="${STORAGE_LOCAL_PATH:-/app/data/uploads}"
# S3 Storage configuration (only used if STORAGE_DRIVER=s3)
export AWS_S3_ACCESS_KEY_ID="${AWS_S3_ACCESS_KEY_ID:-}"
export AWS_S3_SECRET_ACCESS_KEY="${AWS_S3_SECRET_ACCESS_KEY:-}"
export AWS_S3_REGION="${AWS_S3_REGION:-}"
export AWS_S3_BUCKET="${AWS_S3_BUCKET:-}"
export AWS_S3_ENDPOINT="${AWS_S3_ENDPOINT:-}"
export AWS_S3_FORCE_PATH_STYLE="${AWS_S3_FORCE_PATH_STYLE:-false}"
# File upload limits
export FILE_UPLOAD_SIZE_LIMIT="${FILE_UPLOAD_SIZE_LIMIT:-50MB}"
export FILE_IMPORT_SIZE_LIMIT="${FILE_IMPORT_SIZE_LIMIT:-50MB}"
# Application configuration
export APP_URL="${APP_URL:-https://${CLOUDRON_APP_DOMAIN}}"
export APP_SECRET="${APP_SECRET:-${CLOUDRON_APP_ORIGIN}-$(date +%s)}"
export PORT="${PORT:-3001}"
export JWT_TOKEN_EXPIRES_IN="${JWT_TOKEN_EXPIRES_IN:-7d}"
# Diagrams configuration
export DRAWIO_URL="${DRAWIO_URL:-https://embed.diagrams.net}"
# Telemetry (disabled by default for privacy)
export DISABLE_TELEMETRY="${DISABLE_TELEMETRY:-true}"
# Postmark email (alternative to SMTP)
export POSTMARK_TOKEN="${POSTMARK_TOKEN:-}"
echo "=> Email configuration: ${MAIL_DRIVER} via ${SMTP_HOST}:${SMTP_PORT}"
echo "=> Storage configuration: ${STORAGE_DRIVER}"
if [ "${STORAGE_DRIVER}" = "s3" ]; then
echo "=> S3 storage: ${AWS_S3_BUCKET} in ${AWS_S3_REGION}"
fi
# Authentication will use built-in email/password system
echo "=> Using built-in email/password authentication"
# File upload configuration
export FILE_UPLOAD_SIZE_LIMIT="50mb"
@@ -58,10 +174,46 @@ export FILE_UPLOAD_SIZE_LIMIT="50mb"
# JWT configuration
export JWT_TOKEN_EXPIRES_IN="30d"
# Wait for Redis to be available
if [ -n "${CLOUDRON_REDIS_URL}" ]; then
echo "=> Waiting for Redis to be available..."
for i in {1..30}; do
if nc -z "${REDIS_HOST}" "${REDIS_PORT}" 2>/dev/null; then
echo "=> Redis is available"
break
fi
if [ $i -eq 30 ]; then
echo "=> Warning: Redis not reachable after 30 seconds"
fi
sleep 1
done
fi
echo "=> Running database migrations"
cd /app/code
chown -R cloudron:cloudron /app/data
sudo -u cloudron pnpm prisma migrate deploy || true
# Find the correct prisma binary path
PRISMA_BIN=""
if [ -f "/app/code/apps/server/node_modules/.bin/prisma" ]; then
PRISMA_BIN="/app/code/apps/server/node_modules/.bin/prisma"
elif [ -f "/app/code/node_modules/.bin/prisma" ]; then
PRISMA_BIN="/app/code/node_modules/.bin/prisma"
elif [ -f "/app/code/node_modules/@prisma/cli/build/index.js" ]; then
PRISMA_BIN="/usr/bin/node /app/code/node_modules/@prisma/cli/build/index.js"
fi
if [ -n "$PRISMA_BIN" ]; then
echo "=> Found Prisma at: $PRISMA_BIN"
cd /app/code/apps/server
sudo -u cloudron $PRISMA_BIN migrate deploy || true
else
echo "=> Warning: Prisma binary not found, skipping migrations"
fi
# Create nginx temp directories
mkdir -p /tmp/nginx_client_temp /tmp/nginx_proxy_temp /tmp/nginx_fastcgi_temp /tmp/nginx_uwsgi_temp /tmp/nginx_scgi_temp
chown -R cloudron:cloudron /tmp/nginx_*
echo "=> Starting services with supervisor"
exec /usr/bin/supervisord -c /etc/supervisor/conf.d/supervisord.conf

View File

@@ -15,7 +15,7 @@ autorestart=true
priority=100
[program:docmost]
command=/usr/bin/sudo -u cloudron /usr/bin/node /app/code/apps/server/dist/main.js
command=/usr/local/bin/gosu cloudron:cloudron /usr/bin/node /app/code/apps/server/dist/main.js
directory=/app/code
stdout_logfile=/dev/stdout
stdout_logfile_maxbytes=0