Deploying an Alfresco App
Introduction
Alfresco is an open-source enterprise content management system (ECM) designed for managing documents, records, and content across organizations. Built with Java and running on Apache Tomcat, Alfresco provides powerful document management, collaboration, workflow automation, and content services capabilities.
Alfresco is renowned for its:
- Document Management: Comprehensive document storage, versioning, and organization
- Content Services: RESTful API for content access and management
- Workflow Automation: Built-in workflow engine for business process automation
- Collaboration: Team collaboration features with document sharing and commenting
- Search Capabilities: Advanced full-text search with faceted search
- Records Management: Compliance and records management features
- Multi-Format Support: Support for various document formats and media types
- Access Control: Fine-grained permissions and security controls
- Integration: Extensive integration capabilities with other enterprise systems
- Scalability: Designed to handle large-scale content management requirements
Common use cases include document management systems, enterprise content repositories, records management, collaboration platforms, knowledge bases, document workflows, compliance systems, and digital asset management.
This comprehensive guide walks you through deploying Alfresco Content Services on Klutch.sh using a Dockerfile, including detailed installation steps, PostgreSQL database configuration, persistent storage setup, and production-ready best practices for hosting an enterprise content management system.
Prerequisites
Before you begin, ensure you have the following:
- A Klutch.sh account
- A GitHub account with a repository for your Alfresco project
- A PostgreSQL database (can be deployed separately on Klutch.sh or use an external database)
- Docker installed locally for testing (optional but recommended)
- Basic understanding of Java, Tomcat, and enterprise content management systems
- Sufficient compute resources (Alfresco is resource-intensive)
Installation and Setup
Step 1: Create Your Project Directory
First, create a new directory for your Alfresco deployment project:
mkdir alfresco-klutchcd alfresco-klutchgit initStep 2: Prepare Alfresco Source
You can either use the official Alfresco Docker image or prepare a custom Alfresco deployment:
# Option 1: Use the official Alfresco repository structure# Download Alfresco Content Services WAR files and prepare your deployment
# Option 2: If you have a custom Alfresco build# Copy your Alfresco source code to the project directoryStep 3: Create the Dockerfile
Create a Dockerfile in your project root directory. This will define your Alfresco container configuration:
FROM tomcat:9-jdk17-openjdk-slim
# Install system dependenciesRUN apt-get update && apt-get install -y \ curl \ imagemagick \ libreoffice \ ghostscript \ ffmpeg \ && rm -rf /var/lib/apt/lists/*
# Set working directoryWORKDIR /usr/local/tomcat
# Remove default Tomcat webappsRUN rm -rf webapps/*
# Copy Alfresco WAR files# Note: You'll need to download or build these WAR filesCOPY alfresco.war webapps/alfresco.warCOPY share.war webapps/share.war
# Create directories for Alfresco dataRUN mkdir -p /var/lib/alfresco/content \ /var/lib/alfresco/contentstore \ /var/lib/alfresco/indexes \ /var/lib/alfresco/keystore \ /var/lib/alfresco/logs \ /var/lib/alfresco/temp && \ chown -R tomcat:tomcat /var/lib/alfresco
# Copy Alfresco configurationCOPY alfresco-global.properties conf/alfresco-global.properties
# Set environment variablesENV JAVA_OPTS="-Xms2g -Xmx4g -XX:MaxPermSize=512m" \ CATALINA_OPTS="-Djava.awt.headless=true" \ ALFRESCO_HOME=/var/lib/alfresco
# Expose portEXPOSE 8080
# Health checkHEALTHCHECK --interval=30s --timeout=10s --start-period=120s --retries=3 \ CMD curl -f http://localhost:8080/alfresco/api/-default-/public/alfresco/versions/1/profiles/-me- || exit 1
# Start TomcatCMD ["catalina.sh", "run"]Note: This Dockerfile uses Tomcat 9 with Java 17. Alfresco runs on port 8080 by default, which will be your internal port in Klutch.sh. The application requires ImageMagick, LibreOffice, Ghostscript, and FFmpeg for document transformation.
Step 4: Create Alfresco Configuration File
Create an alfresco-global.properties file with production configuration:
alfresco-global.properties:
# Database Configurationdb.driver=org.postgresql.Driverdb.url=jdbc:postgresql://${DB_HOST}:${DB_PORT}/${DB_NAME}db.username=${DB_USER}db.password=${DB_PASSWORD}db.pool.initial=10db.pool.max=275
# Content Store Configurationdir.contentstore=${ALFRESCO_HOME}/contentstoredir.contentstore.deleted=${ALFRESCO_HOME}/contentstore.deleteddir.audit.contentstore=${ALFRESCO_HOME}/audit.contentstore
# Index Configurationdir.indexes=${ALFRESCO_HOME}/indexesdir.indexes.backup=${ALFRESCO_HOME}/indexes.backup
# Temp Directorydir.temp=${ALFRESCO_HOME}/temp
# Loggingdir.logs=${ALFRESCO_HOME}/logs
# Server Configurationalfresco.host=${ALFRESCO_HOST}alfresco.port=8080alfresco.protocol=httpsalfresco.context=alfrescoshare.context=share
# Share Configurationshare.host=${ALFRESCO_HOST}share.port=8080share.protocol=https
# Email Configurationmail.host=${SMTP_HOST}mail.port=${SMTP_PORT:587}mail.username=${SMTP_USER}mail.password=${SMTP_PASSWORD}mail.from.default=${SMTP_FROM:noreply@example.com}mail.protocol=smtpmail.smtp.auth=truemail.smtp.starttls.enable=true
# File System Configurationsystem.webServer.displayName=Alfresco Content Servicessystem.webServer.port=8080
# Content Transformationcontent.transformer.Default.available=trueimg.dyn=${img.root}/ImageMagickooo.exe=/usr/bin/libreofficeooo.enabled=trueimg.root=/usr
# Search Configurationsolr.host=${SOLR_HOST:localhost}solr.port=${SOLR_PORT:8983}solr.port.ssl=${SOLR_PORT_SSL:8983}
# Securitysecurity.anyDenyDenies=falseStep 5: Create Environment Configuration Template
Create a .env.example file with required environment variables:
# Database ConfigurationDB_HOST=your-postgresql-hostDB_PORT=5432DB_NAME=alfrescoDB_USER=alfrescoDB_PASSWORD=your-secure-password
# Application ConfigurationALFRESCO_HOST=example-app.klutch.shALFRESCO_HOME=/var/lib/alfresco
# Storage PathsALFRESCO_CONTENTSTORE=/var/lib/alfresco/contentstoreALFRESCO_INDEXES=/var/lib/alfresco/indexesALFRESCO_LOGS=/var/lib/alfresco/logsALFRESCO_TEMP=/var/lib/alfresco/temp
# Email ConfigurationSMTP_HOST=smtp.example.comSMTP_PORT=587SMTP_USER=your-smtp-usernameSMTP_PASSWORD=your-smtp-passwordSMTP_FROM=noreply@example.com
# Solr Configuration (Optional - if using external Solr)SOLR_HOST=your-solr-hostSOLR_PORT=8983SOLR_PORT_SSL=8983
# Java OptionsJAVA_OPTS=-Xms2g -Xmx4g -XX:MaxPermSize=512m
# TimezoneTZ=UTCStep 6: Create Database Initialization Script
Create a script to initialize the database schema:
scripts/init_db.sh:
#!/bin/bashset -e
echo "Initializing Alfresco database..."
# Wait for PostgreSQL to be readyuntil PGPASSWORD=$DB_PASSWORD psql -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" -d postgres -c '\q'; do >&2 echo "PostgreSQL is unavailable - sleeping" sleep 1done
echo "PostgreSQL is ready"
# Create database if it doesn't existPGPASSWORD=$DB_PASSWORD psql -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" -d postgres <<-EOSQL SELECT 'CREATE DATABASE $DB_NAME' WHERE NOT EXISTS (SELECT FROM pg_database WHERE datname = '$DB_NAME')\gexecEOSQL
echo "Database initialization complete"echo "Alfresco will create the schema automatically on first startup"Step 7: Create .dockerignore File
Create a .dockerignore file to exclude unnecessary files from the Docker build:
.git.gitignore.dockerignore.env.env.local*.mddocker-compose.ymldocker-compose.*.ymlDockerfile*.war*.jarStep 8: Test Locally (Optional)
Before deploying to Klutch.sh, you can test your Alfresco setup locally:
# Build the Docker imagedocker build -t my-alfresco .
# Run the container (assuming you have a PostgreSQL database running)docker run -d \ --name alfresco-test \ -p 8080:8080 \ -e DB_HOST=host.docker.internal \ -e DB_PORT=5432 \ -e DB_NAME=alfresco \ -e DB_USER=alfresco \ -e DB_PASSWORD=password \ -e ALFRESCO_HOST=localhost \ -e SMTP_HOST=smtp.example.com \ -e SMTP_USER=your-smtp-user \ -e SMTP_PASSWORD=your-smtp-password \ -v $(pwd)/contentstore:/var/lib/alfresco/contentstore \ -v $(pwd)/indexes:/var/lib/alfresco/indexes \ my-alfresco
# Check if the application is runningcurl http://localhost:8080/alfresco/api/-default-/public/alfresco/versions/1/profiles/-me-Note: For local development with a database, you can use Docker Compose to run both Alfresco and PostgreSQL together. Docker Compose is only for local development; Klutch.sh does not support Docker Compose for deployment.
Step 9: Push to GitHub
Commit your Alfresco project files to your GitHub repository:
git add .git commit -m "Initial Alfresco Docker setup for Klutch.sh"git branch -M maingit remote add origin https://github.com/yourusername/alfresco-klutch.gitgit push -u origin mainDeploying to Klutch.sh
Now that your Alfresco project is ready and pushed to GitHub, follow these steps to deploy it on Klutch.sh with persistent storage.
Deployment Steps
-
Log in to Klutch.sh
Navigate to klutch.sh/app and sign in to your account.
-
Create a New Project
Go to Create Project and give your project a meaningful name (e.g., “Alfresco Content Management”).
-
Create a New App
Navigate to Create App and configure the following settings:
-
Select Your Repository
- Choose GitHub as your Git source
- Select the repository containing your Dockerfile
- Choose the branch you want to deploy (usually
mainormaster)
Klutch.sh will automatically detect the Dockerfile in your repository root and use it for deployment.
-
Configure Traffic Type
- Traffic Type: Select HTTP (Alfresco is a web application)
- Internal Port: Set to
8080(the port your Alfresco container listens on, as defined in your Dockerfile)
-
Set Environment Variables
Add the following environment variables for your Alfresco configuration:
Database Configuration:
DB_HOST: Your database host (if using a Klutch.sh PostgreSQL app, use the app URL likeexample-db.klutch.sh)DB_PORT: Database port (for Klutch.sh TCP apps, use8000externally, but the internal port in your database app should be5432for PostgreSQL)DB_NAME: Your database name (e.g.,alfresco)DB_USER: Database usernameDB_PASSWORD: Database password
Application Configuration:
ALFRESCO_HOST: Your Klutch.sh app URL (e.g.,example-app.klutch.sh)ALFRESCO_HOME: Set to/var/lib/alfresco
Storage Paths:
ALFRESCO_CONTENTSTORE: Set to/var/lib/alfresco/contentstoreALFRESCO_INDEXES: Set to/var/lib/alfresco/indexesALFRESCO_LOGS: Set to/var/lib/alfresco/logsALFRESCO_TEMP: Set to/var/lib/alfresco/temp
Email Configuration:
SMTP_HOST: Your SMTP server hostnameSMTP_PORT: SMTP port (typically587)SMTP_USER: SMTP usernameSMTP_PASSWORD: SMTP passwordSMTP_FROM: Default sender email address
Optional - Solr Configuration:
SOLR_HOST: Solr server hostname (if using external Solr)SOLR_PORT: Solr port (default:8983)SOLR_PORT_SSL: Solr SSL port
Java Configuration:
JAVA_OPTS: Java runtime options (e.g.,-Xms2g -Xmx4g -XX:MaxPermSize=512m)
Timezone:
TZ: Your timezone (e.g.,UTCorAmerica/New_York)
-
Attach Persistent Volumes
Alfresco requires persistent storage for several directories to ensure data persists across deployments:
Content Store Volume:
- Mount Path:
/var/lib/alfresco/contentstore - Size: Start with 100GB minimum (500GB+ recommended for production with large document collections)
This volume stores:
- All uploaded documents and files
- Document versions
- Media files
- User-generated content
Indexes Volume:
- Mount Path:
/var/lib/alfresco/indexes - Size: Start with 20GB minimum (50GB+ recommended for production)
This volume stores:
- Search indexes
- Lucene index files
- Search metadata
Logs Volume (Optional):
- Mount Path:
/var/lib/alfresco/logs - Size: 10GB (for application logs)
Temp Volume (Optional):
- Mount Path:
/var/lib/alfresco/temp - Size: 10GB (for temporary processing files)
Note: For production instances with large document collections, allocate sufficient storage. Content stores can grow significantly over time, so plan storage capacity accordingly.
- Mount Path:
-
Configure Additional Settings
- Region: Select the region closest to your users for optimal performance
- Compute Resources: Alfresco is resource-intensive; allocate at least:
- CPU: 4+ cores recommended (8+ cores for production)
- Memory: 4GB minimum (8GB+ recommended, 16GB+ for production workloads)
- Instances: Start with 1 instance (you can scale horizontally later if needed)
-
Deploy Your Application
Click “Create” to start the deployment. Klutch.sh will:
- Automatically detect your Dockerfile in the repository root
- Build the Docker image
- Attach the persistent volume(s)
- Start your Alfresco container
- Assign a URL for external access
Note: The first deployment may take several minutes as it builds the Docker image, starts Tomcat, and initializes the Alfresco application. Alfresco will automatically create the database schema on first startup.
-
Access Your Application
Once deployment is complete, you’ll receive a URL like
example-app.klutch.sh. Visit this URL to access your Alfresco instance:- Alfresco Repository:
https://example-app.klutch.sh/alfresco - Alfresco Share:
https://example-app.klutch.sh/share
Default credentials (change immediately):
- Username:
admin - Password:
admin
- Alfresco Repository:
Sample Code: Getting Started with Alfresco
Here are some examples to help you interact with your Alfresco instance:
Example 1: JavaScript Client - Authentication
// Frontend JavaScript example for Alfresco API
async function authenticateAlfresco(username, password) { try { const response = await fetch('https://example-app.klutch.sh/alfresco/api/-default-/public/authentication/versions/1/tickets', { method: 'POST', headers: { 'Content-Type': 'application/json', 'Accept': 'application/json' }, body: JSON.stringify({ userId: username, password: password }) });
if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); }
const authData = await response.json(); console.log('Authentication successful:', authData); return authData; } catch (error) { console.error('Error authenticating:', error); throw error; }}Example 2: Uploading a Document
async function uploadDocument(ticket, file, folderId = '-root-') { try { const formData = new FormData(); formData.append('filedata', file); formData.append('name', file.name);
const response = await fetch( `https://example-app.klutch.sh/alfresco/api/-default-/public/alfresco/versions/1/nodes/${folderId}/children`, { method: 'POST', headers: { 'Authorization': `Basic ${btoa(ticket)}`, 'Accept': 'application/json' }, body: formData } );
if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); }
const document = await response.json(); console.log('Document uploaded:', document); return document; } catch (error) { console.error('Error uploading document:', error); throw error; }}Example 3: Searching Documents
async function searchDocuments(ticket, query) { try { const params = new URLSearchParams({ term: query, maxItems: 50 });
const response = await fetch( `https://example-app.klutch.sh/alfresco/api/-default-/public/search/versions/1/search?${params}`, { method: 'GET', headers: { 'Authorization': `Basic ${btoa(ticket)}`, 'Accept': 'application/json' } } );
if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); }
const results = await response.json(); console.log('Search Results:', results); return results; } catch (error) { console.error('Error searching documents:', error); throw error; }}Example 4: Python Client Example
import requestsimport base64from requests.auth import HTTPBasicAuth
class AlfrescoClient: def __init__(self, base_url): self.base_url = base_url self.ticket = None
def authenticate(self, username, password): """Authenticate and get ticket""" response = requests.post( f'{self.base_url}/alfresco/api/-default-/public/authentication/versions/1/tickets', json={'userId': username, 'password': password} ) response.raise_for_status() data = response.json() self.ticket = data.get('entry', {}).get('id') return self.ticket
def upload_document(self, file_path, folder_id='-root-'): """Upload a document""" if not self.ticket: raise ValueError("Not authenticated. Call authenticate() first.")
with open(file_path, 'rb') as f: files = {'filedata': f} data = {'name': file_path.split('/')[-1]}
response = requests.post( f'{self.base_url}/alfresco/api/-default-/public/alfresco/versions/1/nodes/{folder_id}/children', auth=HTTPBasicAuth(self.ticket, ''), files=files, data=data ) response.raise_for_status() return response.json()
def search_documents(self, query, max_items=50): """Search for documents""" if not self.ticket: raise ValueError("Not authenticated. Call authenticate() first.")
params = {'term': query, 'maxItems': max_items} response = requests.get( f'{self.base_url}/alfresco/api/-default-/public/search/versions/1/search', auth=HTTPBasicAuth(self.ticket, ''), params=params ) response.raise_for_status() return response.json()
def get_node(self, node_id): """Get node information""" if not self.ticket: raise ValueError("Not authenticated. Call authenticate() first.")
response = requests.get( f'{self.base_url}/alfresco/api/-default-/public/alfresco/versions/1/nodes/{node_id}', auth=HTTPBasicAuth(self.ticket, '') ) response.raise_for_status() return response.json()
# Example usageclient = AlfrescoClient('https://example-app.klutch.sh')
# Authenticateclient.authenticate('admin', 'admin')
# Search for documentsresults = client.search_documents('test document')print(f"Found {len(results.get('list', {}).get('entries', []))} documents")
# Upload a documentupload_result = client.upload_document('/path/to/document.pdf')print(f"Uploaded document: {upload_result['entry']['id']}")Production Best Practices
Security Recommendations
- Enable HTTPS: Always use HTTPS in production (Klutch.sh provides TLS certificates)
- Secure Environment Variables: Store all sensitive credentials as environment variables in Klutch.sh
- Database Security: Use strong database passwords and enable SSL connections
- Change Default Credentials: Immediately change the default admin credentials
- Access Control: Implement proper access control and permissions
- Regular Updates: Keep Alfresco and dependencies updated with security patches
- Backup Strategy: Regularly backup your database and content store
- Audit Logging: Enable audit logging for compliance requirements
- Input Validation: Always validate and sanitize user input
- Network Security: Implement network-level security controls
Performance Optimization
- Database Optimization: Regularly optimize PostgreSQL database with VACUUM and ANALYZE
- Connection Pooling: Configure appropriate database connection pool sizes
- Caching: Implement caching strategies for frequently accessed content
- CDN Integration: Consider using a CDN for static assets
- Resource Monitoring: Monitor CPU, memory, and storage usage
- Index Optimization: Regularly optimize search indexes
- Content Transformation: Configure appropriate content transformation settings
- JVM Tuning: Optimize Java heap size and garbage collection settings
Content Management Best Practices
- Storage Planning: Plan storage capacity based on expected content volume
- Backup Strategy: Implement regular backups of content store and database
- Version Control: Use version control for important documents
- Retention Policies: Implement document retention and archival policies
- Metadata Management: Maintain proper metadata for all documents
- Access Control: Establish clear access control policies
- Content Organization: Organize content with proper folder structures
Monitoring and Maintenance
Monitor your Alfresco application for:
- Application Logs: Check logs in Klutch.sh dashboard for errors
- Database Performance: Monitor query performance and slow queries
- Storage Usage: Monitor persistent volume usage and plan for growth
- Response Times: Track API response times
- Error Rates: Monitor 4xx and 5xx error rates
- Resource Usage: Track CPU and memory usage in Klutch.sh dashboard
- Content Growth: Monitor content store growth
Regular maintenance tasks:
- Backup Database: Regularly backup your PostgreSQL database
- Backup Content Store: Backup content store from persistent volumes
- Update Dependencies: Keep Java dependencies updated
- Review Logs: Review application and error logs regularly
- Security Audits: Perform regular security audits
- Database Maintenance: Regularly run database maintenance tasks
- Index Maintenance: Rebuild indexes if needed
- Storage Cleanup: Clean up old versions and deleted content
Troubleshooting
Application Not Loading
- Verify the app’s Traffic Type is HTTP
- Check that the internal port is set to
8080and matches your Dockerfile - Review build and runtime logs in the Klutch.sh dashboard
- Ensure the Tomcat application starts correctly (check the CMD in Dockerfile)
- Verify all required environment variables are set
- Check Java heap size settings
Database Connection Issues
- Verify database environment variables are set correctly
- For Klutch.sh PostgreSQL apps, use the app URL as the host and port
8000externally - Check that the database is accessible from your Alfresco app
- Verify database credentials and permissions
- Ensure the database exists and is accessible
- Check database connection pool settings
Content Upload Issues
- Ensure persistent volume is mounted at
/var/lib/alfresco/contentstore - Check file permissions on the content store directory
- Verify sufficient disk space in the persistent volume
- Review content transformation settings
- Check LibreOffice and ImageMagick installation
Search Issues
- Verify search index configuration
- Check index directory permissions
- Rebuild search indexes if necessary
- Review Solr configuration if using external Solr
- Check search query logs
Performance Issues
- Review database query performance and add indexes if needed
- Check resource allocation in Klutch.sh (CPU and memory)
- Monitor database connection pool usage
- Review application logs for slow operations
- Consider increasing Java heap size
- Optimize content transformation settings
- Review and optimize search indexes
Data Not Persisting
- Ensure persistent volumes are correctly mounted
- Check file permissions on persistent volumes
- Verify the application is writing to the correct directories
- Ensure sufficient disk space in persistent volumes
Related Documentation
- Learn more about deploying applications on Klutch.sh in Deployments
- Understand traffic types, ports, and routing in Networking
- Explore how to work with storage in Volumes
- Browse the full platform documentation at Klutch.sh Documentation
- For Alfresco-specific details, see the official Alfresco Documentation
- Learn about enterprise content management best practices
Conclusion
Deploying Alfresco to Klutch.sh with a Dockerfile provides a scalable, reliable enterprise content management system with persistent storage, automatic deployments, and production-ready configuration. By following this guide, you’ve set up a high-performance Alfresco instance with proper data persistence, security configurations, and the ability to handle large-scale content management requirements.
Alfresco’s comprehensive document management capabilities, workflow automation, and enterprise features make it an excellent choice for organizations needing robust content management. Your application is now ready to store, organize, and manage documents while maintaining security and performance.
Remember to follow the production best practices outlined in this guide, regularly monitor your application performance, and adjust resources as your content collection grows. With proper configuration, monitoring, and maintenance, Alfresco on Klutch.sh will provide a reliable, secure foundation for your enterprise content management needs.