Compare commits
5 Commits
65cd9a73bb
...
main
Author | SHA1 | Date | |
---|---|---|---|
|
5f8238cbc2 | ||
|
a64e79e3fc | ||
|
e2a2665fb1 | ||
|
fe3e9fc27e | ||
|
34ef0803d8 |
127
CONFIGURATION.md
127
CONFIGURATION.md
@@ -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
|
|
@@ -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.
|
|
@@ -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 && \
|
||||||
|
15
README.md
15
README.md
@@ -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
|
||||||
|
@@ -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();
|
|
@@ -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;
|
|
14
package.json
14
package.json
@@ -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"
|
|
||||||
}
|
|
||||||
}
|
|
21
start.sh
21
start.sh
@@ -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
|
||||||
|
Reference in New Issue
Block a user