Deploying a HedgeDoc App
Introduction
HedgeDoc is a powerful open-source collaborative markdown editor that enables real-time collaboration, perfect for team documentation, note-taking, and knowledge sharing. Deploying HedgeDoc on Klutch.sh provides you with a scalable, production-ready platform featuring automatic Dockerfile detection, persistent storage for your data, secure environment variable management, and seamless GitHub integration.
This comprehensive guide walks you through deploying HedgeDoc with a Dockerfile on Klutch.sh, from initial setup and installation to production-ready configurations with persistent volumes and database integration. Whether you’re setting up HedgeDoc for personal use, team collaboration, or as part of your organization’s documentation infrastructure, this guide covers everything you need to know.
Prerequisites
Before you begin deploying HedgeDoc on Klutch.sh, ensure you have:
- A Klutch.sh account (sign up here)
- A GitHub account with a repository for your HedgeDoc deployment
- Basic understanding of Docker and containerization concepts
- Familiarity with environment variables and configuration management
- (Optional) A PostgreSQL or MySQL database for production deployments
What is HedgeDoc?
HedgeDoc (formerly known as CodiMD) is a feature-rich, real-time collaborative markdown editor. It allows multiple users to simultaneously edit documents, supports various markdown extensions, integrates with external services, and provides presentation modes for your markdown content. HedgeDoc is ideal for technical documentation, meeting notes, project planning, and any scenario where collaborative editing is valuable.
Key features include:
- Real-time collaborative editing with multiple users
- Rich markdown support including diagrams, math equations, and code highlighting
- Export to PDF, HTML, and various other formats
- Version history and revision tracking
- Multiple authentication providers (OAuth, LDAP, SAML)
- Presentation mode for markdown slides
Getting Started: Project Setup
Let’s start by setting up your HedgeDoc project structure for deployment on Klutch.sh.
1. Create Your Project Repository
First, create a new GitHub repository for your HedgeDoc deployment:
mkdir hedgedoc-klutchcd hedgedoc-klutchgit init2. Create a Dockerfile
Klutch.sh automatically detects and uses a Dockerfile when present in your repository’s root directory. Create a Dockerfile with the following content:
# Use the official HedgeDoc imageFROM quay.io/hedgedoc/hedgedoc:1.9.9
# Expose the default HedgeDoc portEXPOSE 3000
# The official image already includes the necessary CMD# CMD ["node", "app.js"]This Dockerfile uses the official HedgeDoc image from Quay.io. The image is pre-configured with all necessary dependencies and will run HedgeDoc on port 3000.
3. Create a .gitignore File
Create a .gitignore file to exclude sensitive and unnecessary files:
# Environment files.env.env.local
# Logslogs*.log
# OS files.DS_StoreThumbs.db
# IDE files.vscode/.idea/4. Create a README
Document your deployment with a README.md:
# HedgeDoc on Klutch.sh
This repository contains the configuration for deploying HedgeDoc on Klutch.sh.
## Deployment
1. Push this repository to GitHub2. Create a new app in Klutch.sh dashboard3. Connect your GitHub repository4. Configure environment variables5. Deploy!
## Environment Variables
See the Klutch.sh dashboard for required environment variables.5. Initialize Git and Push to GitHub
git add .git commit -m "Initial HedgeDoc setup for Klutch.sh"git remote add origin https://github.com/your-username/hedgedoc-klutch.gitgit push -u origin mainDeploying HedgeDoc on Klutch.sh
Now that your repository is ready, let’s deploy HedgeDoc on Klutch.sh. The platform will automatically detect your Dockerfile and build your container.
-
Log in to Klutch.sh Dashboard
Navigate to klutch.sh/app and log in to your account.
-
Create a New Project (if you haven’t already)
Projects help organize your applications. Create a new project for your HedgeDoc deployment or use an existing one.
-
Create a New App
Click on “Create App” or “New App” in your project dashboard.
-
Connect Your GitHub Repository
- Select GitHub as your Git source
- Authorize Klutch.sh to access your repositories if prompted
- Select the repository containing your HedgeDoc Dockerfile
- Choose the branch you want to deploy (typically
mainormaster)
-
Configure Deployment Settings
Klutch.sh will automatically detect the Dockerfile in your repository root. Configure the following settings:
- Traffic Type: Select HTTP (HedgeDoc serves web traffic)
- Internal Port: Set to 3000 (HedgeDoc’s default port)
- Region: Choose the region closest to your users
- Compute Resources: Select appropriate instance size based on expected usage
- For testing: Smallest available instance
- For production: Medium or larger instance depending on team size
-
Configure Environment Variables
HedgeDoc requires several environment variables for configuration. Add these in the Klutch.sh dashboard:
Basic Configuration:
CMD_DOMAIN=example-app.klutch.shCMD_URL_ADDPORT=falseCMD_PROTOCOL_USESSL=trueCMD_PORT=3000Database Configuration (SQLite for testing):
CMD_DB_URL=sqlite:///hedgedoc/db/hedgedoc.sqliteSession Secret (generate a secure random string):
CMD_SESSION_SECRET=your-secure-random-string-hereFor production deployments with PostgreSQL:
CMD_DB_URL=postgres://username:password@hostname:5432/databaseCMD_DB_DIALECT=postgresSee the Environment Variables section below for more configuration options.
-
Set Up Persistent Storage
HedgeDoc needs persistent storage for uploads and database files:
- Click “Add Volume” or navigate to the Volumes section
- Mount Path:
/hedgedoc/public/uploads(for user uploads) - Size: Start with 5GB, scale up as needed
If using SQLite, add another volume:
- Mount Path:
/hedgedoc/db - Size: 2GB
Note: You specify only the mount path and size; Klutch.sh manages the volume automatically.
-
Deploy Your Application
Click “Create” or “Deploy” to start the deployment process. Klutch.sh will:
- Pull your repository from GitHub
- Detect the Dockerfile automatically
- Build the Docker image
- Create the container with your configuration
- Mount the persistent volumes
- Route traffic to your application
-
Verify Deployment
Once deployment completes, your HedgeDoc instance will be available at
example-app.klutch.sh(or your configured domain). Visit the URL to access HedgeDoc and complete the initial setup.
Environment Variables Configuration
HedgeDoc uses environment variables for configuration. Here’s a comprehensive list of important variables to configure in the Klutch.sh dashboard:
Essential Variables
# Domain and URL ConfigurationCMD_DOMAIN=example-app.klutch.shCMD_URL_ADDPORT=falseCMD_PROTOCOL_USESSL=trueCMD_PORT=3000
# Database (SQLite - for testing only)CMD_DB_URL=sqlite:///hedgedoc/db/hedgedoc.sqlite
# Session Security (generate a strong random string)CMD_SESSION_SECRET=change-this-to-a-long-random-stringProduction Database Variables (PostgreSQL)
For production deployments, use PostgreSQL instead of SQLite:
# PostgreSQL ConfigurationCMD_DB_URL=postgres://hedgedoc_user:secure_password@your-db-host:5432/hedgedoc_dbCMD_DB_DIALECT=postgres
# Alternative format using individual variablesCMD_DB_HOST=your-db-hostCMD_DB_PORT=5432CMD_DB_DATABASE=hedgedoc_dbCMD_DB_USERNAME=hedgedoc_userCMD_DB_PASSWORD=secure_passwordCMD_DB_DIALECT=postgresMySQL Configuration (Alternative)
If you prefer MySQL:
CMD_DB_URL=mysql://hedgedoc_user:secure_password@your-db-host:3306/hedgedoc_dbCMD_DB_DIALECT=mysqlAuthentication Configuration
Enable various authentication methods:
# Email RegistrationCMD_ALLOW_EMAIL_REGISTER=trueCMD_EMAIL=true
# GitHub OAuthCMD_OAUTH2_CLIENT_ID=your-github-oauth-client-idCMD_OAUTH2_CLIENT_SECRET=your-github-oauth-client-secretCMD_OAUTH2_AUTHORIZATION_URL=https://github.com/login/oauth/authorizeCMD_OAUTH2_TOKEN_URL=https://github.com/login/oauth/access_tokenCMD_OAUTH2_USER_PROFILE_URL=https://api.github.com/user
# Google OAuthCMD_GOOGLE_CLIENT_ID=your-google-client-idCMD_GOOGLE_CLIENT_SECRET=your-google-client-secret
# LDAPCMD_LDAP_URL=ldap://ldap.example.comCMD_LDAP_BIND_DN=cn=admin,dc=example,dc=comCMD_LDAP_BIND_CREDENTIALS=passwordCMD_LDAP_SEARCH_BASE=ou=users,dc=example,dc=comCMD_LDAP_SEARCH_FILTER=(uid={{username}})Image Upload Configuration
Configure image upload settings:
# Image Upload Type (filesystem, imgur, s3, azure, etc.)CMD_IMAGE_UPLOAD_TYPE=filesystem
# For S3-compatible storage:CMD_IMAGE_UPLOAD_TYPE=s3CMD_S3_ACCESS_KEY_ID=your-access-keyCMD_S3_SECRET_ACCESS_KEY=your-secret-keyCMD_S3_REGION=us-east-1CMD_S3_BUCKET=hedgedoc-uploadsSecurity and Performance
# Require authentication for readingCMD_REQUIRE_FREEURL_AUTHENTICATION=falseCMD_ALLOW_ANONYMOUS=trueCMD_ALLOW_ANONYMOUS_EDITS=true
# Rate limitingCMD_RATE_LIMIT_FREE_USER_MINUTES=50CMD_RATE_LIMIT_FREE_USER_LIMIT=50
# HSTS (HTTP Strict Transport Security)CMD_HSTS_ENABLE=trueCMD_HSTS_MAX_AGE=31536000CMD_HSTS_INCLUDE_SUBDOMAINS=trueCMD_HSTS_PRELOAD=true
# CSP (Content Security Policy)CMD_CSP_ENABLE=trueSecurity Best Practice: Always store sensitive values (passwords, API keys, secrets) as secret environment variables in the Klutch.sh dashboard. Never commit them to your repository.
Advanced Dockerfile Configuration
For more control over your HedgeDoc deployment, you can create a custom Dockerfile with additional configurations:
Multi-Stage Dockerfile with Custom Plugins
FROM node:18-alpine AS builder
# Install build dependenciesRUN apk add --no-cache \ python3 \ make \ g++ \ git
WORKDIR /hedgedoc
# Clone HedgeDoc repositoryRUN git clone --depth 1 --branch 1.9.9 https://github.com/hedgedoc/hedgedoc.git .
# Install dependencies and buildRUN yarn install --frozen-lockfile && \ yarn run build
# Production stageFROM node:18-alpine
# Install runtime dependenciesRUN apk add --no-cache \ tini \ ca-certificates
WORKDIR /hedgedoc
# Copy built application from builderCOPY --from=builder /hedgedoc /hedgedoc
# Create necessary directoriesRUN mkdir -p /hedgedoc/public/uploads /hedgedoc/db && \ chown -R node:node /hedgedoc
# Switch to non-root userUSER node
# Expose portEXPOSE 3000
# Use tini to handle signals properlyENTRYPOINT ["/sbin/tini", "--"]
# Start HedgeDocCMD ["node", "app.js"]Dockerfile with Custom Configuration File
FROM quay.io/hedgedoc/hedgedoc:1.9.9
# Copy custom configurationCOPY config.json /hedgedoc/config.json
# Ensure proper permissionsUSER rootRUN chown hedgedoc:hedgedoc /hedgedoc/config.jsonUSER hedgedoc
EXPOSE 3000Persistent Storage Best Practices
Proper persistent storage configuration is crucial for HedgeDoc to retain user data across deployments.
Required Mount Points
For SQLite deployments:
-
Database Storage:
- Mount Path:
/hedgedoc/db - Size: 2-5GB (depending on expected usage)
- Purpose: Stores the SQLite database file
- Mount Path:
-
Upload Storage:
- Mount Path:
/hedgedoc/public/uploads - Size: 5-20GB (depending on user activity)
- Purpose: Stores user-uploaded images and files
- Mount Path:
For PostgreSQL/MySQL deployments:
- Upload Storage (only):
- Mount Path:
/hedgedoc/public/uploads - Size: 5-20GB (depending on user activity)
- Purpose: Stores user-uploaded images and files
- Note: Database is external, so no DB volume needed
- Mount Path:
Configuring Volumes in Klutch.sh
When creating or editing your app in the Klutch.sh dashboard:
- Navigate to the “Volumes” or “Storage” section
- Click “Add Volume”
- Enter the mount path (e.g.,
/hedgedoc/db) - Specify the size in GB
- Repeat for each required mount point
The platform automatically manages volume creation, attachment, and persistence. Your data will remain intact across deployments and restarts.
Database Options: SQLite vs PostgreSQL vs MySQL
Choosing the right database depends on your deployment scale and requirements.
SQLite (Development and Small Teams)
Pros:
- No external database required
- Simple setup with minimal configuration
- Perfect for testing and personal use
- Low resource requirements
Cons:
- Limited concurrent user capacity
- Not suitable for high-traffic deployments
- Requires persistent volume for data retention
Configuration:
CMD_DB_URL=sqlite:///hedgedoc/db/hedgedoc.sqlitePostgreSQL (Recommended for Production)
Pros:
- Excellent performance with concurrent users
- Robust transaction support
- Better scalability
- Advanced features and reliability
Cons:
- Requires separate database instance
- More complex setup
- Additional resource costs
Configuration:
CMD_DB_URL=postgres://username:password@hostname:5432/databaseCMD_DB_DIALECT=postgresMySQL/MariaDB (Alternative Production Option)
Pros:
- Wide compatibility and support
- Good performance
- Familiar to many administrators
Cons:
- Slightly less feature-rich than PostgreSQL for HedgeDoc
- Requires separate database instance
Configuration:
CMD_DB_URL=mysql://username:password@hostname:3306/databaseCMD_DB_DIALECT=mysqlProduction Database Setup
For production deployments using PostgreSQL:
- Provision a PostgreSQL database (via Klutch.sh or external provider)
- Create a dedicated database and user:
CREATE DATABASE hedgedoc_db;CREATE USER hedgedoc_user WITH ENCRYPTED PASSWORD 'secure_password';GRANT ALL PRIVILEGES ON DATABASE hedgedoc_db TO hedgedoc_user;- Note the connection details (host, port, database name, username, password)
- Configure the
CMD_DB_URLenvironment variable in Klutch.sh - Deploy your HedgeDoc app
The app will automatically connect to your database and create the necessary tables on first startup.
Setting Up Authentication
HedgeDoc supports multiple authentication methods. Here’s how to configure common options:
Email Registration
Enable users to register with email addresses:
CMD_ALLOW_EMAIL_REGISTER=trueCMD_EMAIL=trueGitHub OAuth
-
Create an OAuth App in GitHub:
- Go to GitHub Settings → Developer settings → OAuth Apps
- Click “New OAuth App”
- Set Authorization callback URL to:
https://example-app.klutch.sh/auth/github/callback - Note the Client ID and Client Secret
-
Configure in Klutch.sh:
CMD_OAUTH2_CLIENT_ID=your-github-client-idCMD_OAUTH2_CLIENT_SECRET=your-github-client-secretCMD_OAUTH2_AUTHORIZATION_URL=https://github.com/login/oauth/authorizeCMD_OAUTH2_TOKEN_URL=https://github.com/login/oauth/access_tokenCMD_OAUTH2_USER_PROFILE_URL=https://api.github.com/userGoogle OAuth
- Create OAuth credentials in Google Cloud Console
- Configure authorized redirect URI:
https://example-app.klutch.sh/auth/google/callback - Add to Klutch.sh:
CMD_GOOGLE_CLIENT_ID=your-google-client-idCMD_GOOGLE_CLIENT_SECRET=your-google-client-secretLDAP Authentication
For enterprise deployments with existing LDAP infrastructure:
CMD_LDAP_URL=ldap://ldap.example.comCMD_LDAP_BIND_DN=cn=admin,dc=example,dc=comCMD_LDAP_BIND_CREDENTIALS=admin_passwordCMD_LDAP_SEARCH_BASE=ou=users,dc=example,dc=comCMD_LDAP_SEARCH_FILTER=(uid={{username}})CMD_LDAP_SEARCH_ATTRIBUTES=displayName,mailCMD_LDAP_TLS_CA=/path/to/ca.pemMonitoring and Scaling
Monitoring Your HedgeDoc Instance
Monitor these key metrics in the Klutch.sh dashboard:
- CPU Usage: High CPU might indicate many concurrent users or heavy processing
- Memory Usage: Watch for memory leaks or insufficient allocation
- Disk Usage: Track volume usage, especially for uploads and SQLite databases
- Response Times: Monitor application performance
- Error Rates: Check logs for errors or issues
Scaling Strategies
Vertical Scaling (Increasing instance size):
- Upgrade to larger compute instances for more CPU and memory
- Suitable for moderate traffic increases
- Simpler to implement
Horizontal Scaling (Multiple instances):
- Deploy multiple instances behind a load balancer
- Requires external database (PostgreSQL/MySQL)
- Requires shared storage for uploads (S3 or similar)
- Better for high-availability setups
Database Scaling:
- Use connection pooling
- Optimize database queries
- Consider read replicas for PostgreSQL
- Regular maintenance and vacuuming
Custom Domains and SSL
To use a custom domain with your HedgeDoc deployment:
-
Add Custom Domain in Klutch.sh:
- Navigate to your app settings
- Go to the “Domains” or “Custom Domains” section
- Add your domain (e.g.,
docs.example.com)
-
Configure DNS:
- Add a CNAME record pointing to your Klutch.sh app URL
- Or use A/AAAA records as provided by Klutch.sh
-
Update Environment Variables:
CMD_DOMAIN=docs.example.comCMD_URL_ADDPORT=falseCMD_PROTOCOL_USESSL=true- SSL/TLS:
- Klutch.sh automatically manages SSL certificates
- Certificates are provisioned and renewed automatically
- Ensure your domain is properly configured before accessing
Backup and Disaster Recovery
Database Backups
For SQLite:
# From within the container or via volume accesssqlite3 /hedgedoc/db/hedgedoc.sqlite ".backup /backups/hedgedoc-$(date +%Y%m%d).sqlite"For PostgreSQL:
# From a client machine with pg_dumppg_dump -h hostname -U hedgedoc_user hedgedoc_db > hedgedoc-backup-$(date +%Y%m%d).sqlFor MySQL:
mysqldump -h hostname -u hedgedoc_user -p hedgedoc_db > hedgedoc-backup-$(date +%Y%m%d).sqlBackup Strategy Recommendations
-
Automated Backups:
- Schedule regular database backups (daily or hourly for critical deployments)
- Use managed database backup features if available
- Store backups in object storage (S3, etc.)
-
Upload Storage Backups:
- Regularly backup the
/hedgedoc/public/uploadsvolume - Consider using S3 or similar object storage for uploads
- Implement versioning if available
- Regularly backup the
-
Configuration Backups:
- Document all environment variables
- Keep Dockerfile and deployment configuration in version control
- Maintain runbooks for disaster recovery
-
Testing Recovery:
- Periodically test restore procedures
- Verify backup integrity
- Document recovery time objectives (RTO)
Troubleshooting Common Issues
Application Won’t Start
Symptoms: Container crashes or doesn’t start
Solutions:
- Check environment variables are correctly set
- Verify database connection (test connectivity to database host)
- Review container logs in Klutch.sh dashboard
- Ensure persistent volumes are properly mounted
- Check for port conflicts (internal port should be 3000)
Database Connection Errors
Symptoms: “Connection refused” or “Authentication failed” errors
Solutions:
- Verify database credentials in environment variables
- Check database host is accessible from your Klutch.sh app
- Ensure database exists and user has proper permissions
- For PostgreSQL, verify
pg_hba.confallows connections - Test connection:
psql -h hostname -U username -d database
Cannot Upload Images
Symptoms: Upload button doesn’t work or shows errors
Solutions:
- Verify persistent volume is mounted at
/hedgedoc/public/uploads - Check volume has sufficient space available
- Ensure proper file permissions (container user needs write access)
- Review
CMD_IMAGE_UPLOAD_TYPEenvironment variable - Check browser console for JavaScript errors
Slow Performance
Symptoms: Pages load slowly, editing is laggy
Solutions:
- Check resource usage (CPU, memory) in Klutch.sh dashboard
- Consider upgrading to larger instance
- Optimize database (vacuum, analyze, reindex)
- Check database connection pool settings
- Review concurrent user count vs available resources
- Consider switching from SQLite to PostgreSQL if using SQLite
SSL/HTTPS Issues
Symptoms: Certificate errors or insecure connection warnings
Solutions:
- Verify
CMD_PROTOCOL_USESSL=trueis set - Check custom domain DNS is properly configured
- Ensure
CMD_DOMAINmatches actual domain - Wait for SSL certificate provisioning (can take a few minutes)
- Check Klutch.sh domain configuration
Authentication Not Working
Symptoms: Cannot log in, OAuth fails
Solutions:
- Verify OAuth credentials are correct
- Check callback URLs match your domain exactly
- Review OAuth app settings in provider (GitHub, Google, etc.)
- Ensure
CMD_DOMAINis correctly set - Check for typos in client IDs and secrets
- Review error messages in container logs
Data Loss After Deployment
Symptoms: Notes disappear after redeployment
Solutions:
- Verify persistent volumes are properly configured
- Check volumes are attached to correct mount paths
- Ensure SQLite database path matches volume mount
- Don’t use ephemeral storage for critical data
- Implement regular backups (see Backup section)
Security Best Practices
Environment Variable Security
- Never commit secrets to Git: Use Klutch.sh’s environment variable management
- Mark sensitive variables as secret: Use the secret/hidden option in dashboard
- Rotate credentials regularly: Change database passwords and API keys periodically
- Use strong session secrets: Generate cryptographically secure random strings
- Limit access: Only grant database permissions needed by HedgeDoc
Network Security
- Use HTTPS always: Set
CMD_PROTOCOL_USESSL=true - Enable HSTS:
CMD_HSTS_ENABLE=true - Configure CSP:
CMD_CSP_ENABLE=true - Restrict database access: Use private networks or VPCs when possible
- Implement rate limiting: Use built-in HedgeDoc rate limiting features
Authentication and Access Control
- Require authentication: Set
CMD_ALLOW_ANONYMOUS=falsefor private deployments - Use OAuth with trusted providers: GitHub, Google, or enterprise SSO
- Implement 2FA: If your OAuth provider supports it
- Regular access reviews: Audit user accounts periodically
- Disable unnecessary auth methods: Only enable what you need
Application Security
- Keep HedgeDoc updated: Use specific version tags and update regularly
- Monitor security advisories: Subscribe to HedgeDoc security notifications
- Regular security audits: Review logs and access patterns
- Implement backups: See Backup section for strategies
- Test disaster recovery: Ensure you can restore from backups
Production Deployment Checklist
Use this checklist before deploying HedgeDoc to production:
- PostgreSQL or MySQL database provisioned and configured
- Database backups configured and tested
- Persistent volumes created for uploads
- All environment variables configured correctly
- Secrets stored securely in Klutch.sh (not in repository)
- Custom domain configured with SSL
- Authentication method(s) configured and tested
-
CMD_ALLOW_ANONYMOUSset according to requirements - Image upload storage configured (filesystem or S3)
- Rate limiting configured appropriately
- HSTS and CSP enabled
- Monitoring configured for CPU, memory, disk
- Logging configured and accessible
- Disaster recovery plan documented
- Backup restoration tested
- Performance testing completed under expected load
- Security review completed
- User documentation prepared
Resources and Further Reading
- HedgeDoc Official Documentation
- HedgeDoc GitHub Repository
- Klutch.sh Quick Start Guide
- Klutch.sh Volumes Documentation
- Klutch.sh Deployments Documentation
- Klutch.sh Networking Documentation
- Klutch.sh Custom Domains Documentation
Conclusion
Deploying HedgeDoc on Klutch.sh provides a robust, scalable solution for collaborative markdown editing. With automatic Dockerfile detection, managed infrastructure, persistent storage, and seamless GitHub integration, Klutch.sh simplifies the deployment process while giving you full control over your HedgeDoc configuration.
Whether you’re running a small team wiki, managing technical documentation, or providing a collaborative note-taking platform for your organization, HedgeDoc on Klutch.sh offers the reliability and features you need. Start with the SQLite configuration for testing, then scale to PostgreSQL with multiple instances as your needs grow.
For questions, issues, or feature requests related to deployment on Klutch.sh, visit the Klutch.sh documentation or reach out to support. For HedgeDoc-specific questions, consult the official HedgeDoc documentation and community forums.